From a218dd046050b473cdb7559466848d29fe84d940 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 23 Sep 2023 20:01:50 +0800 Subject: [PATCH 001/129] add 2.7.1 to springboot2.x --- pom.xml | 11 +++++----- springboot-starter-data-fast/pom.xml | 4 ++-- .../fast/DataFastConfiguration.java | 2 +- .../springboot/fast/executor/JpaExecutor.java | 2 +- .../springboot/fast/executor/JpaQuery.java | 6 +++--- .../fast/manager/EntityManagerContent.java | 3 ++- .../manager/EntityManagerInitializer.java | 3 ++- .../springboot/fast/entity/Demo.java | 3 ++- springboot-starter-id-generator/pom.xml | 4 ++-- .../springboot/generator/dao/IdKeyDao.java | 4 ++-- springboot-starter-security-jwt/pom.xml | 4 ++-- .../security/AutoConfiguration.java | 4 ++-- .../configurer/WebSecurityConfigurer.java | 2 +- .../filter/MyAccessDeniedHandler.java | 6 +++--- .../filter/MyAuthenticationFilter.java | 9 ++++---- .../security/filter/MyLoginFilter.java | 8 +++---- .../security/filter/MyLogoutHandler.java | 5 +++-- .../filter/MyLogoutSuccessHandler.java | 6 +++--- .../filter/MyUnAuthenticationEntryPoint.java | 7 ++++--- .../security/filter/SecurityLoginHandler.java | 5 +++-- springboot-starter/pom.xml | 8 +++---- .../framework/dto/request/PageRequest.java | 2 +- .../framework/rest/param/RestParam.java | 6 ++++-- ...HandlerExceptionResolverConfiguration.java | 5 +++-- .../utils/TrustAnyHttpClientFactory.java | 21 ++++++++++--------- .../framework/query/entity/Demo.java | 3 ++- 26 files changed, 76 insertions(+), 67 deletions(-) diff --git a/pom.xml b/pom.xml index 3ba9ed9b..49600c4f 100644 --- a/pom.xml +++ b/pom.xml @@ -6,25 +6,25 @@ org.springframework.boot spring-boot-starter-parent - 3.1.2 + 2.7.16 com.codingapi.springboot springboot-parent - 2.1.11 + 2.7.1 https://github.com/codingapi/springboot-framewrok springboot-parent springboot-parent project for Spring Boot - 17 + 8 yyyy-MM-dd HH:mm:ss - 17 - 17 + 8 + 8 3.0.1 3.11.0 2.10.3 @@ -39,7 +39,6 @@ 0.9.16 1.70 1.2.0 - 2.0 diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 141c3862..d06408f0 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,14 +5,14 @@ springboot-parent com.codingapi.springboot - 2.1.11 + 2.7.1 4.0.0 springboot-starter-data-fast - 17 + 8 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java index 0dcf4268..f977da31 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java @@ -12,7 +12,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; -import jakarta.persistence.EntityManager; +import javax.persistence.EntityManager; import java.util.List; @Configuration diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaExecutor.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaExecutor.java index 04067091..a7795989 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaExecutor.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaExecutor.java @@ -5,7 +5,7 @@ import lombok.AllArgsConstructor; import org.springframework.data.domain.Page; -import jakarta.persistence.EntityManager; +import javax.persistence.EntityManager; import java.util.Collection; import java.util.List; diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaQuery.java index dbc4e118..0aa880f0 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaQuery.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaQuery.java @@ -7,9 +7,9 @@ import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; -import jakarta.persistence.EntityManager; -import jakarta.persistence.Parameter; -import jakarta.persistence.Query; +import javax.persistence.EntityManager; +import javax.persistence.Parameter; +import javax.persistence.Query; import java.lang.reflect.Field; import java.util.Set; diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerContent.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerContent.java index 3d7d5c59..96ab6ba2 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerContent.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerContent.java @@ -1,8 +1,9 @@ package com.codingapi.springboot.fast.manager; -import jakarta.persistence.EntityManager; import lombok.Getter; +import javax.persistence.EntityManager; + public class EntityManagerContent { @Getter diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerInitializer.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerInitializer.java index ea87bea4..a262fc20 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerInitializer.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerInitializer.java @@ -1,9 +1,10 @@ package com.codingapi.springboot.fast.manager; -import jakarta.persistence.EntityManager; import lombok.AllArgsConstructor; import org.springframework.beans.factory.InitializingBean; +import javax.persistence.EntityManager; + @AllArgsConstructor public class EntityManagerInitializer implements InitializingBean { diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java index 3e9e66d8..a39afa5d 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java @@ -3,7 +3,8 @@ import lombok.Getter; import lombok.Setter; -import jakarta.persistence.*; +import javax.persistence.*; + @Setter @Getter diff --git a/springboot-starter-id-generator/pom.xml b/springboot-starter-id-generator/pom.xml index c4adbf85..96cf9c71 100644 --- a/springboot-starter-id-generator/pom.xml +++ b/springboot-starter-id-generator/pom.xml @@ -5,14 +5,14 @@ springboot-parent com.codingapi.springboot - 2.1.11 + 2.7.1 4.0.0 springboot-starter-id-generator - 17 + 8 diff --git a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/IdKeyDao.java b/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/IdKeyDao.java index 59332bc0..541a68a5 100644 --- a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/IdKeyDao.java +++ b/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/IdKeyDao.java @@ -62,7 +62,7 @@ public List query(Connection connection, QueryRunner queryRunner) throws @SneakyThrows public IdKey updateMaxId(IdKey generator) { - return dbHelper.updateAndQuery(new DbHelper.IUpdateAndQuery<>() { + return dbHelper.updateAndQuery(new DbHelper.IUpdateAndQuery>() { @Override public List updateAndQuery(Connection connection, QueryRunner queryRunner) throws SQLException { queryRunner.update(connection, "UPDATE ID_GENERATOR SET ID = ID + 1 WHERE TAG = ?", generator.getKey()); @@ -74,7 +74,7 @@ public List updateAndQuery(Connection connection, QueryRunner queryRunner @SneakyThrows public List findAll() throws SQLException { - return dbHelper.query(new DbHelper.IQuery<>() { + return dbHelper.query(new DbHelper.IQuery>() { @Override public List query(Connection connection, QueryRunner queryRunner) throws SQLException { return queryRunner.query(connection, "SELECT * FROM ID_GENERATOR", handler); diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index 6369c486..f3ed9bd4 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.1.11 + 2.7.1 springboot-starter-security-jwt @@ -15,7 +15,7 @@ springboot-starter-security-jwt project for Spring Boot - 17 + 8 diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java index ba56c691..7587aaa0 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java @@ -82,8 +82,8 @@ public SecurityFilterChain filterChain(HttpSecurity security, Jwt jwt,SecurityLo .and() .authorizeHttpRequests( registry -> { - registry.requestMatchers(properties.getIgnoreUrls()).permitAll() - .requestMatchers(properties.getAuthenticatedUrls()).authenticated() + registry.antMatchers(properties.getIgnoreUrls()).permitAll() + .antMatchers(properties.getAuthenticatedUrls()).authenticated() .anyRequest().permitAll(); } ) diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/WebSecurityConfigurer.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/WebSecurityConfigurer.java index 7e5f3e75..5bd1ebd5 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/WebSecurityConfigurer.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/WebSecurityConfigurer.java @@ -15,7 +15,7 @@ public class WebSecurityConfigurer implements WebSecurityCustomizer { @Override public void customize(WebSecurity web) { //ignoring security filters request url - web.ignoring().requestMatchers(securityJwtProperties.getIgnoreUrls()); + web.ignoring().antMatchers(securityJwtProperties.getIgnoreUrls()); } } diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java index 191d1dfc..4387a65b 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java @@ -7,9 +7,9 @@ import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java index 09562919..aaa348a7 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java @@ -6,10 +6,6 @@ import com.codingapi.springboot.security.jwt.Jwt; import com.codingapi.springboot.security.jwt.Token; import com.codingapi.springboot.security.properties.SecurityJwtProperties; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.springframework.security.authentication.AuthenticationManager; @@ -17,8 +13,11 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.util.AntPathMatcher; import org.springframework.util.StringUtils; -import org.springframework.web.filter.OncePerRequestFilter; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java index f472ed99..bbfc55af 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java @@ -22,10 +22,10 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.stream.Collectors; diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutHandler.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutHandler.java index a27c9d76..b2cbe8d2 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutHandler.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutHandler.java @@ -4,8 +4,9 @@ import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.logout.LogoutHandler; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + @Slf4j public class MyLogoutHandler implements LogoutHandler { diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java index 16a86c68..7ed35833 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java @@ -7,9 +7,9 @@ import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java index ecc91b95..c1e610f8 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java @@ -7,9 +7,10 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java index 5ad14115..b8ce2a2a 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java @@ -2,8 +2,9 @@ import com.codingapi.springboot.security.dto.request.LoginRequest; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + public interface SecurityLoginHandler { diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 30709242..8a71dc0a 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,14 +5,14 @@ com.codingapi.springboot springboot-parent - 2.1.11 + 2.7.1 springboot-starter springboot-starter springboot-starter project for Spring Boot - 17 + 8 @@ -47,8 +47,8 @@ - org.apache.httpcomponents.client5 - httpclient5 + org.apache.httpcomponents + httpclient diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index b7af6da8..77f99ae0 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -1,6 +1,5 @@ package com.codingapi.springboot.framework.dto.request; -import jakarta.servlet.http.HttpServletRequest; import lombok.Getter; import org.springframework.beans.BeanUtils; import org.springframework.data.domain.Example; @@ -10,6 +9,7 @@ import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +import javax.servlet.http.HttpServletRequest; import java.beans.PropertyDescriptor; import java.util.Enumeration; import java.util.HashMap; diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java index 51c08a8b..a19efe09 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java @@ -41,9 +41,11 @@ private static void fetch(JSONObject object, RestParam builder) { fetch(jsonObject, builder); } - if (value instanceof JSONArray jsonArray) { + if (value instanceof JSONArray) { + JSONArray jsonArray = (JSONArray) value; for (Object o : jsonArray) { - if (o instanceof JSONObject jsonObject) { + if (o instanceof JSONObject) { + JSONObject jsonObject = (JSONObject) o; fetch(jsonObject, builder); } } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/servlet/BasicHandlerExceptionResolverConfiguration.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/servlet/BasicHandlerExceptionResolverConfiguration.java index 573de914..8cf34dc3 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/servlet/BasicHandlerExceptionResolverConfiguration.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/servlet/BasicHandlerExceptionResolverConfiguration.java @@ -2,8 +2,6 @@ import com.codingapi.springboot.framework.exception.LocaleMessageException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; @@ -12,6 +10,9 @@ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.json.MappingJackson2JsonView; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + @Configuration @ConditionalOnClass(name = "org.springframework.web.servlet.HandlerExceptionResolver") public class BasicHandlerExceptionResolverConfiguration { diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/TrustAnyHttpClientFactory.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/TrustAnyHttpClientFactory.java index 25810885..2bc34c3d 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/TrustAnyHttpClientFactory.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/TrustAnyHttpClientFactory.java @@ -2,16 +2,17 @@ import lombok.SneakyThrows; -import org.apache.hc.client5.http.classic.HttpClient; -import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.client5.http.impl.classic.HttpClients; -import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager; -import org.apache.hc.client5.http.socket.ConnectionSocketFactory; -import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; -import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; -import org.apache.hc.core5.http.config.Registry; -import org.apache.hc.core5.http.config.RegistryBuilder; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; + import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; diff --git a/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/entity/Demo.java b/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/entity/Demo.java index 664f815a..148a34ae 100644 --- a/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/entity/Demo.java +++ b/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/entity/Demo.java @@ -1,9 +1,10 @@ package com.codingapi.springboot.framework.query.entity; -import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; +import javax.persistence.*; + @Setter @Getter @Table(name = "t_demo") From 76b7b8dffedacdc4be1c5536eab547464945c9ae Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Tue, 26 Sep 2023 10:30:41 +0800 Subject: [PATCH 002/129] fix getExample() 2.7.2 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../springboot/fast/query/FastRepository.java | 34 +++- .../springboot/fast/query/QueryRequest.java | 147 ++++++++++++++++++ springboot-starter-id-generator/pom.xml | 2 +- springboot-starter-security-jwt/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/dto/request/PageRequest.java | 144 ++++++++++++----- .../framework/rest/param/RestParam.java | 5 +- .../query/test/DemoRepositoryTest.java | 6 +- 10 files changed, 294 insertions(+), 52 deletions(-) create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java diff --git a/pom.xml b/pom.xml index 49600c4f..c03da97d 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.1 + 2.7.2 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index d06408f0..85efb421 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.1 + 2.7.2 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java index 71eeb9ae..937b5928 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java @@ -1,21 +1,27 @@ package com.codingapi.springboot.fast.query; import com.codingapi.springboot.framework.dto.request.PageRequest; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Predicate; import org.springframework.core.ResolvableType; import org.springframework.data.domain.Page; +import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.NoRepositoryBean; +import java.util.List; + @NoRepositoryBean -public interface FastRepository extends JpaRepository, JpaSpecificationExecutor { +public interface FastRepository extends JpaRepository, JpaSpecificationExecutor { - default Page findAll(PageRequest request){ - if(request.hasFilter()){ + default Page findAll(PageRequest request) { + if (request.hasFilter()) { Class clazz = getDomainClass(); - return findAll(request.getExample(clazz),request); + QueryRequest queryRequest = new QueryRequest(request, clazz); + return findAll(queryRequest.getExample(), request); } - return findAll((org.springframework.data.domain.PageRequest)request); + return findAll((org.springframework.data.domain.PageRequest) request); } @@ -25,4 +31,20 @@ default Class getDomainClass() { return (Class) resolvableType.getGeneric(0).resolve(); } -} + + default Page findAllByRequest(PageRequest request) { + if (request.hasFilter()) { + Class clazz = getDomainClass(); + Specification specification = (root, query, criteriaBuilder) -> { + QueryRequest queryRequest = new QueryRequest(request, clazz); + List predicates = queryRequest.getPredicate(root, criteriaBuilder); + List orderList = queryRequest.getOrder(root, criteriaBuilder); + return query.where(predicates.toArray(new Predicate[0])).orderBy(orderList).getRestriction(); + }; + + return findAll(specification, request); + } + return findAll((org.springframework.data.domain.PageRequest) request); + } + +} \ No newline at end of file diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java new file mode 100644 index 00000000..32056ce4 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java @@ -0,0 +1,147 @@ +package com.codingapi.springboot.fast.query; + +import com.codingapi.springboot.framework.dto.request.PageRequest; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import org.springframework.beans.BeanUtils; +import org.springframework.data.domain.Example; + +import java.beans.PropertyDescriptor; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class QueryRequest { + + private final PageRequest request; + private final Class clazz; + + public QueryRequest(PageRequest request, Class clazz) { + this.request = request; + this.clazz = clazz; + } + + public Example getExample() { + if (!request.hasFilter()) { + return null; + } + Object entity = null; + try { + entity = clazz.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz); + for (PropertyDescriptor descriptor : descriptors) { + String name = descriptor.getName(); + PageRequest.Filter value = request.getFilters().get(name); + if (value != null) { + try { + descriptor.getWriteMethod().invoke(entity, value.getFilterValue(descriptor.getPropertyType())); + } catch (Exception e) { + } + } + } + return (Example) Example.of(entity); + } + + + public List getOrder(Root root, CriteriaBuilder criteriaBuilder) { + List orderList = new ArrayList<>(); + request.getSort().forEach(sort -> { + if (sort.getDirection().isAscending()) { + orderList.add(criteriaBuilder.asc(root.get(sort.getProperty()))); + } else { + orderList.add(criteriaBuilder.asc(root.get(sort.getProperty()))); + } + }); + return orderList; + } + + public List getPredicate(Root root, CriteriaBuilder criteriaBuilder) { + List predicates = new ArrayList<>(); + for (String key : request.getFilters().keySet()) { + PageRequest.Filter filter = request.getFilters().get(key); + if (filter.isEqual()) { + predicates.add(criteriaBuilder.equal(root.get(key), filter.getValue()[0])); + } + + if (filter.isLike()) { + String matchValue = (String) filter.getValue()[0]; + predicates.add(criteriaBuilder.like(root.get(key), "%" + matchValue + "%")); + } + + if (filter.isBetween()) { + Object value1 = filter.getValue()[0]; + Object value2 = filter.getValue()[2]; + if (value1 instanceof Integer && value2 instanceof Integer) { + predicates.add(criteriaBuilder.between(root.get(key), (Integer) value1, (Integer) value2)); + } + + if (value1 instanceof Long && value2 instanceof Long) { + predicates.add(criteriaBuilder.between(root.get(key), (Long) value1, (Long) value2)); + } + + if (value1 instanceof Date && value2 instanceof Date) { + predicates.add(criteriaBuilder.between(root.get(key), (Date) value1, (Date) value2)); + } + } + + if (filter.isGreaterThan()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + predicates.add(criteriaBuilder.greaterThan(root.get(key), (Integer) value)); + } + if (value instanceof Long) { + predicates.add(criteriaBuilder.greaterThan(root.get(key), (Long) value)); + } + if (value instanceof Date) { + predicates.add(criteriaBuilder.greaterThan(root.get(key), (Date) value)); + } + } + + if (filter.isGreaterThanEqual()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Integer) value)); + } + if (value instanceof Long) { + predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Long) value)); + } + if (value instanceof Date) { + predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Date) value)); + } + } + + if (filter.isLessThan()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + predicates.add(criteriaBuilder.lessThan(root.get(key), (Integer) value)); + } + if (value instanceof Long) { + predicates.add(criteriaBuilder.lessThan(root.get(key), (Long) value)); + } + if (value instanceof Date) { + predicates.add(criteriaBuilder.lessThan(root.get(key), (Date) value)); + } + } + + if (filter.isLessThanEqual()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Integer) value)); + } + if (value instanceof Long) { + predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Long) value)); + } + if (value instanceof Date) { + predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Date) value)); + } + } + } + + return predicates; + } +} \ No newline at end of file diff --git a/springboot-starter-id-generator/pom.xml b/springboot-starter-id-generator/pom.xml index 96cf9c71..3f3a6a34 100644 --- a/springboot-starter-id-generator/pom.xml +++ b/springboot-starter-id-generator/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.1 + 2.7.2 4.0.0 diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index f3ed9bd4..68c74e24 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.1 + 2.7.2 springboot-starter-security-jwt diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 8a71dc0a..74016e37 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.1 + 2.7.2 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index 77f99ae0..42e71cef 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -1,16 +1,14 @@ package com.codingapi.springboot.framework.dto.request; +import javax.servlet.http.HttpServletRequest; import lombok.Getter; -import org.springframework.beans.BeanUtils; -import org.springframework.data.domain.Example; +import lombok.Setter; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import javax.servlet.http.HttpServletRequest; -import java.beans.PropertyDescriptor; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; @@ -22,7 +20,8 @@ public class PageRequest extends org.springframework.data.domain.PageRequest { private int current; private int pageSize; - private final Map filters = new HashMap<>(); + @Getter + private final Map filters = new HashMap<>(); @Getter private HttpServletRequest servletRequest; @@ -50,7 +49,7 @@ private void syncParameter() { String key = enumeration.nextElement(); String value = servletRequest.getParameter(key); if (StringUtils.hasText(value)) { - this.filters.put(key, value); + addFilter(key, value); } } } @@ -81,26 +80,41 @@ public int getIntParameter(String key, int defaultValue) { return result == null ? defaultValue : Integer.parseInt(result); } - public Map getFilters() { - return filters; - } public String getStringFilter(String key) { - return (String) filters.get(key); + Filter filter = (Filter) filters.get(key); + if (filter != null) { + return (String) filter.getValue()[0]; + } + return null; } public String getStringFilter(String key, String defaultValue) { - String result = (String) filters.get(key); - return result == null ? defaultValue : result; + String value = getStringFilter(key); + if (!StringUtils.hasText(value)) { + return defaultValue; + } + return value; } public int getIntFilter(String key) { - return Integer.parseInt((String) filters.get(key)); + Filter filter = (Filter) filters.get(key); + if (filter != null) { + String value = (String) filter.getValue()[0]; + if (StringUtils.hasText(value)) { + return Integer.parseInt(value); + } + return 0; + } + return 0; } public int getIntFilter(String key, int defaultValue) { - String result = (String) filters.get(key); - return result == null ? defaultValue : Integer.parseInt(result); + int value = getIntFilter(key); + if (value == 0) { + return defaultValue; + } + return value; } @@ -182,38 +196,96 @@ public void addSort(Sort sort) { } } - public PageRequest addFilter(String key, Object value) { - this.filters.put(key, value); + public PageRequest addFilter(String key, FilterRelation relation, Object... value) { + putFilter(key, relation, value); return this; } + public PageRequest addFilter(String key, Object... value) { + return this.addFilter(key, FilterRelation.EUQAL, value); + } + public boolean hasFilter() { return !this.filters.isEmpty(); } - public Example getExample(Class clazz) { - if (!hasFilter()) { - return null; + @Setter + @Getter + public static class Filter { + private String key; + private Object[] value; + + private FilterRelation relation; + + public boolean isEqual() { + return relation == FilterRelation.EUQAL; } - Object entity = null; - try { - entity = clazz.getDeclaredConstructor().newInstance(); - } catch (Exception e) { - throw new RuntimeException(e); - } - PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz); - for (PropertyDescriptor descriptor : descriptors) { - String name = descriptor.getName(); - Object value = filters.get(name); - if (value != null) { - try { - descriptor.getWriteMethod().invoke(entity, value); - } catch (Exception e) { + + public boolean isLike() { + return relation == FilterRelation.LIKE; + } + + public boolean isBetween() { + return relation == FilterRelation.BETWEEN; + } + + public boolean isIn() { + return relation == FilterRelation.IN; + } + + public boolean isGreaterThan() { + return relation == FilterRelation.GREATER_THAN; + } + + public boolean isLessThan() { + return relation == FilterRelation.LESS_THAN; + } + + public boolean isGreaterThanEqual() { + return relation == FilterRelation.GREATER_THAN_EQUAL; + } + + public boolean isLessThanEqual() { + return relation == FilterRelation.LESS_THAN_EQUAL; + } + + public Object getFilterValue(Class clazz) { + Object val = value[0]; + if(val instanceof String) { + if(clazz == Integer.class) { + return Integer.parseInt((String)val); + } + if(clazz == Long.class) { + return Long.parseLong((String)val); + } + if(clazz == Double.class) { + return Double.parseDouble((String)val); + } + if(clazz == Float.class) { + return Float.parseFloat((String)val); } } + return value[0]; } - return (Example) Example.of(entity); } -} + private void putFilter(String key, FilterRelation relation, Object... val) { + Filter filter = new Filter(); + filter.setKey(key); + filter.setValue(val); + filter.setRelation(relation); + this.filters.put(key, filter); + } + + public enum FilterRelation { + EUQAL, + LIKE, + BETWEEN, + IN, + GREATER_THAN, + LESS_THAN, + GREATER_THAN_EQUAL, + LESS_THAN_EQUAL, + } +} \ No newline at end of file diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java index a19efe09..7ad699a5 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java @@ -2,11 +2,11 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import lombok.SneakyThrows; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; public class RestParam { @@ -66,9 +66,10 @@ public RestParam add(String key, Object value) { return add(key, value, true); } + @SneakyThrows public RestParam add(String key, Object value, boolean encode) { String stringValue = value.toString(); - String encodeValue = encode ? URLEncoder.encode(stringValue, StandardCharsets.UTF_8) : value.toString(); + String encodeValue = encode ? URLEncoder.encode(stringValue, "UTF-8") : value.toString(); jsonBody.put(key, value); mapBody.add(key, encodeValue); return this; diff --git a/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/test/DemoRepositoryTest.java b/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/test/DemoRepositoryTest.java index 3ae7c3e2..a35c577f 100644 --- a/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/test/DemoRepositoryTest.java +++ b/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/test/DemoRepositoryTest.java @@ -46,9 +46,9 @@ void query(){ request.setCurrent(1); request.setPageSize(10); - request.addFilter("name","123"); - - Example demo = request.getExample(Demo.class); + Demo search = new Demo(); + search.setName("123"); + Example demo = Example.of(search); System.out.println(demo); Page page = demoRepository.findAll(demo,request); assertEquals(1, page.getTotalElements()); From 3d2742a5d21da8a7810d423456b1689d77cbb11f Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 6 Oct 2023 11:06:21 +0800 Subject: [PATCH 003/129] add SortRepository & DynamicRepository --- .../fast/dynamic/DynamicConfiguration.java | 21 ++++++++ .../springboot/fast/dynamic/DynamicQuery.java | 50 +++++++++++++++++++ .../fast/dynamic/DynamicQueryContext.java | 23 +++++++++ .../dynamic/DynamicQueryContextRegister.java | 16 ++++++ .../fast/dynamic/DynamicRepository.java | 39 +++++++++++++++ .../springboot/fast/query/FastRepository.java | 7 +-- .../codingapi/springboot/fast/sort/ISort.java | 8 +++ .../springboot/fast/sort/SortRepository.java | 21 ++++++++ .../main/resources/META-INF/spring.factories | 3 +- ...ot.autoconfigure.AutoConfiguration.imports | 3 +- 10 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicConfiguration.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQuery.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContext.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContextRegister.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicRepository.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/ISort.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicConfiguration.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicConfiguration.java new file mode 100644 index 00000000..1fe09262 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicConfiguration.java @@ -0,0 +1,21 @@ +package com.codingapi.springboot.fast.dynamic; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.persistence.EntityManager; + +@Configuration +public class DynamicConfiguration { + + @Bean + public DynamicQuery dynamicQuery(EntityManager entityManager){ + return new DynamicQuery(entityManager); + } + + @Bean + public DynamicQueryContextRegister dynamicQueryContextRegister(DynamicQuery dynamicQuery){ + return new DynamicQueryContextRegister(dynamicQuery); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQuery.java new file mode 100644 index 00000000..5727d337 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQuery.java @@ -0,0 +1,50 @@ +package com.codingapi.springboot.fast.dynamic; + +import lombok.AllArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; + +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import java.util.List; + +@AllArgsConstructor +public class DynamicQuery { + + private final EntityManager entityManager; + + public List listQuery(Class clazz, String sql, Object... params) { + TypedQuery query = entityManager.createQuery(sql, clazz); + if (params != null) { + for (int i = 0; i < params.length; i++) { + query.setParameter(i + 1, params[i]); + } + } + return query.getResultList(); + } + + public Page pageQuery(Class clazz, String sql, String countSql, PageRequest pageRequest, Object... params) { + TypedQuery query = entityManager.createQuery(sql, clazz); + if (params != null) { + for (int i = 0; i < params.length; i++) { + query.setParameter(i + 1, params[i]); + } + } + query.setFirstResult(pageRequest.getPageNumber() * pageRequest.getPageSize()); + query.setMaxResults(pageRequest.getPageSize()); + return new PageImpl<>(query.getResultList(), pageRequest, countQuery(countSql, params)); + } + + + private long countQuery(String sql, Object... params) { + TypedQuery query = entityManager.createQuery(sql, Long.class); + if (params != null) { + for (int i = 0; i < params.length; i++) { + query.setParameter(i + 1, params[i]); + } + } + return query.getSingleResult(); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContext.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContext.java new file mode 100644 index 00000000..7e1e9230 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContext.java @@ -0,0 +1,23 @@ +package com.codingapi.springboot.fast.dynamic; + + +import lombok.Getter; + +public class DynamicQueryContext { + + @Getter + private static final DynamicQueryContext instance = new DynamicQueryContext(); + + private DynamicQueryContext() { + + } + + @Getter + private DynamicQuery dynamicQuery; + + void setDynamicQuery(DynamicQuery dynamicQuery) { + this.dynamicQuery = dynamicQuery; + } + + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContextRegister.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContextRegister.java new file mode 100644 index 00000000..4ed1cb8d --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContextRegister.java @@ -0,0 +1,16 @@ +package com.codingapi.springboot.fast.dynamic; + +import lombok.AllArgsConstructor; +import org.springframework.beans.factory.InitializingBean; + +@AllArgsConstructor +public class DynamicQueryContextRegister implements InitializingBean { + + private DynamicQuery dynamicQuery; + + @Override + public void afterPropertiesSet() throws Exception { + DynamicQueryContext.getInstance().setDynamicQuery(dynamicQuery); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicRepository.java new file mode 100644 index 00000000..fffd31a4 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicRepository.java @@ -0,0 +1,39 @@ +package com.codingapi.springboot.fast.dynamic; + +import org.springframework.core.ResolvableType; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.NoRepositoryBean; + +import java.util.List; + +@NoRepositoryBean +public interface DynamicRepository extends JpaRepository { + + default Class getEntityClass() { + ResolvableType resolvableType = ResolvableType.forClass(this.getClass()).as(DynamicRepository.class); + return resolvableType.getGeneric(new int[]{0}).resolve(); + } + + default List dynamicListQuery(String sql, Object... params) { + return (List) DynamicQueryContext.getInstance().getDynamicQuery().listQuery(getEntityClass(), sql, params); + } + + default List dynamicListQuery(Class clazz, String sql, Object... params) { + return (List) DynamicQueryContext.getInstance().getDynamicQuery().listQuery(clazz, sql, params); + } + + default Page dynamicPageQuery(String sql, String countSql, PageRequest request, Object... params) { + return (Page) DynamicQueryContext.getInstance().getDynamicQuery().pageQuery(getEntityClass(), sql, countSql, request, params); + } + + default Page dynamicPageQuery(String sql, PageRequest request, Object... params) { + return (Page) DynamicQueryContext.getInstance().getDynamicQuery().pageQuery(getEntityClass(), sql, "select count(1) " + sql, request, params); + } + + default Page dynamicPageQuery(Class clazz, String sql, String countSql, PageRequest request, Object... params) { + return (Page) DynamicQueryContext.getInstance().getDynamicQuery().pageQuery(clazz, sql, countSql, request, params); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java index 937b5928..5ee1f504 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java @@ -1,8 +1,7 @@ package com.codingapi.springboot.fast.query; +import com.codingapi.springboot.fast.dynamic.DynamicRepository; import com.codingapi.springboot.framework.dto.request.PageRequest; -import javax.persistence.criteria.Order; -import javax.persistence.criteria.Predicate; import org.springframework.core.ResolvableType; import org.springframework.data.domain.Page; import org.springframework.data.jpa.domain.Specification; @@ -10,10 +9,12 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.NoRepositoryBean; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Predicate; import java.util.List; @NoRepositoryBean -public interface FastRepository extends JpaRepository, JpaSpecificationExecutor { +public interface FastRepository extends JpaRepository, JpaSpecificationExecutor, DynamicRepository { default Page findAll(PageRequest request) { if (request.hasFilter()) { diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/ISort.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/ISort.java new file mode 100644 index 00000000..b4a689d3 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/ISort.java @@ -0,0 +1,8 @@ +package com.codingapi.springboot.fast.sort; + +public interface ISort { + + Integer getSort(); + + void setSort(Integer sort); +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java new file mode 100644 index 00000000..b13f5120 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java @@ -0,0 +1,21 @@ +package com.codingapi.springboot.fast.sort; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.NoRepositoryBean; + +import java.util.List; + +@NoRepositoryBean +public interface SortRepository extends JpaRepository { + + + default void sort(PageRequest request, List ids) { + for (int i = 0; i < ids.size(); i++) { + ISort entity = getById((I) ids.get(i)); + entity.setSort(i + ((request.getPageNumber() - 1) * request.getPageSize())); + save((T) entity); + } + } + +} diff --git a/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories b/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories index 545e7ce2..99726f46 100644 --- a/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories +++ b/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories @@ -1,3 +1,4 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.codingapi.springboot.fast.DataFastConfiguration,\ -com.codingapi.springboot.fast.registrar.DataFastBeanDefinitionRegistrar \ No newline at end of file +com.codingapi.springboot.fast.registrar.DataFastBeanDefinitionRegistrar,\ +com.codingapi.springboot.fast.dynamic.DynamicConfiguration diff --git a/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index c1debcb6..e8f74008 100644 --- a/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1,3 @@ com.codingapi.springboot.fast.DataFastConfiguration -com.codingapi.springboot.fast.registrar.DataFastBeanDefinitionRegistrar \ No newline at end of file +com.codingapi.springboot.fast.registrar.DataFastBeanDefinitionRegistrar +com.codingapi.springboot.fast.dynamic.DynamicConfiguration \ No newline at end of file From ed49e4264a4ed430550d5530935bbaee7b052c8d Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 6 Oct 2023 19:14:21 +0800 Subject: [PATCH 004/129] fix PageRequest.java --- docs/wiki/springboot-starter-data-fast.md | 159 ++++++++++++++++++ .../springboot/fast/query/FastRepository.java | 2 +- .../springboot/fast/sort/SortRepository.java | 15 +- .../springboot/fast/DemoRepositoryTest.java | 97 ++++++++++- .../springboot/fast/entity/Demo.java | 6 +- .../fast/repository/DemoRepository.java | 3 +- .../framework/dto/request/PageRequest.java | 31 ++-- 7 files changed, 285 insertions(+), 28 deletions(-) diff --git a/docs/wiki/springboot-starter-data-fast.md b/docs/wiki/springboot-starter-data-fast.md index 0466431d..154795dc 100644 --- a/docs/wiki/springboot-starter-data-fast.md +++ b/docs/wiki/springboot-starter-data-fast.md @@ -2,6 +2,7 @@ springboot-starter-data-fast 基于JPA的快速API能力服务 +## FastController 快速API能力服务 ```java package com.codingapi.springboot.example.query; @@ -45,3 +46,161 @@ value为查询语句,countQuery为查询总数语句,query为查询参数, MultiResponse为返回结果 @PreAuthorize(value = "hasRole('ROLE_USER')") 用于标记当前接口的权限,如果不需要权限可以不用添加 +## FastRepository 的使用教程 + + +继承FastRepository接口,实现自定义的接口,即可使用FastRepository的能力 +```java + + +import com.codingapi.springboot.fast.entity.Demo; +import com.codingapi.springboot.fast.query.FastRepository; + +public interface DemoRepository extends FastRepository { + +} + + +``` +动态FastRepository的能力展示 + +```java + + // 重写findAll,通过Example查询 + @Test + void findAll() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + PageRequest request = new PageRequest(); + request.setCurrent(1); + request.setPageSize(10); + request.addFilter("name", "123"); + + Page page = demoRepository.findAll(request); + assertEquals(1, page.getTotalElements()); + } + + + // pageRequest 自定义条件查询 + @Test + void pageRequest() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + PageRequest request = new PageRequest(); + request.setCurrent(1); + request.setPageSize(10); + request.addFilter("name", PageRequest.FilterRelation.LIKE, "%2%"); + + Page page = demoRepository.pageRequest(request); + assertEquals(1, page.getTotalElements()); + } + + + // 动态sql的List查询 + @Test + void dynamicListQuery() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + List list = demoRepository.dynamicListQuery("from Demo where name = ?1", "123"); + assertEquals(1, list.size()); + } + + + // 动态sql的分页查询 + @Test + void dynamicPageQuery() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + Page page = demoRepository.dynamicPageQuery("from Demo where name = ?1", PageRequest.of(1, 2), "123"); + assertEquals(1, page.getTotalElements()); + } + + // 增加排序查询 + @Test + void sortQuery() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + PageRequest request = new PageRequest(); + request.setCurrent(1); + request.setPageSize(10); + + request.addSort(Sort.by("id").descending()); + Page page = demoRepository.findAll(request); + assertEquals(page.getContent().get(0).getName(), "456"); + assertEquals(2, page.getTotalElements()); + } + +``` +## SortRepository的使用教程 + +```java + +public interface DemoRepository extends FastRepository, SortRepository { + +} + +``` + +SortRepository的能力展示 + +```java + + @Test + @Transactional + void pageSort() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + List ids = Arrays.asList(demo1.getId(), demo2.getId()); + System.out.println(ids); + demoRepository.pageSort(PageRequest.of(1, 10), ids); + + Demo newDemo1 = demoRepository.getReferenceById(demo1.getId()); + Demo newDemo2 = demoRepository.getReferenceById(demo2.getId()); + + assertEquals(newDemo2.getSort(), 1); + assertEquals(newDemo1.getSort(), 0); + } + +``` \ No newline at end of file diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java index 5ee1f504..c1a4374d 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java @@ -33,7 +33,7 @@ default Class getDomainClass() { } - default Page findAllByRequest(PageRequest request) { + default Page pageRequest(PageRequest request) { if (request.hasFilter()) { Class clazz = getDomainClass(); Specification specification = (root, query, criteriaBuilder) -> { diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java index b13f5120..499ecd34 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java @@ -1,21 +1,24 @@ package com.codingapi.springboot.fast.sort; -import org.springframework.data.domain.PageRequest; +import com.codingapi.springboot.framework.dto.request.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.repository.NoRepositoryBean; +import java.util.ArrayList; import java.util.List; @NoRepositoryBean -public interface SortRepository extends JpaRepository { +public interface SortRepository extends JpaRepository { - default void sort(PageRequest request, List ids) { + default void pageSort(PageRequest request, List ids) { + List list = new ArrayList<>(); for (int i = 0; i < ids.size(); i++) { - ISort entity = getById((I) ids.get(i)); - entity.setSort(i + ((request.getPageNumber() - 1) * request.getPageSize())); - save((T) entity); + ISort entity = getReferenceById(ids.get(i)); + entity.setSort(i + (request.getPageNumber() * request.getPageSize())); + list.add((T) entity); } + saveAll(list); } } diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index 283fd318..c1e74ebb 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -8,6 +8,10 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.Page; import org.springframework.data.domain.Sort; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -20,17 +24,17 @@ public class DemoRepositoryTest { @Test - void test(){ + void test() { demoRepository.deleteAll(); Demo demo = new Demo(); demo.setName("123"); demoRepository.save(demo); - assertTrue(demo.getId()>0); + assertTrue(demo.getId() > 0); } @Test - void query(){ + void findAll() { demoRepository.deleteAll(); Demo demo1 = new Demo(); demo1.setName("123"); @@ -43,15 +47,68 @@ void query(){ PageRequest request = new PageRequest(); request.setCurrent(1); request.setPageSize(10); - request.addFilter("name","123"); + request.addFilter("name", "123"); - Page page = demoRepository.findAll(request); + Page page = demoRepository.findAll(request); assertEquals(1, page.getTotalElements()); } @Test - void sort(){ + void pageRequest() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + PageRequest request = new PageRequest(); + request.setCurrent(1); + request.setPageSize(10); + request.addFilter("name", PageRequest.FilterRelation.LIKE, "%2%"); + + Page page = demoRepository.pageRequest(request); + assertEquals(1, page.getTotalElements()); + } + + + @Test + void dynamicListQuery() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + List list = demoRepository.dynamicListQuery("from Demo where name = ?1", "123"); + assertEquals(1, list.size()); + } + + + @Test + void dynamicPageQuery() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + Page page = demoRepository.dynamicPageQuery("from Demo where name = ?1", PageRequest.of(1, 2), "123"); + assertEquals(1, page.getTotalElements()); + } + + + @Test + void sortQuery() { demoRepository.deleteAll(); Demo demo1 = new Demo(); demo1.setName("123"); @@ -66,8 +123,32 @@ void sort(){ request.setPageSize(10); request.addSort(Sort.by("id").descending()); - Page page = demoRepository.findAll(request); - assertEquals(page.getContent().get(0).getName(),"456"); + Page page = demoRepository.findAll(request); + assertEquals(page.getContent().get(0).getName(), "456"); assertEquals(2, page.getTotalElements()); } + + + @Test + @Transactional + void pageSort() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + List ids = Arrays.asList(demo1.getId(), demo2.getId()); + System.out.println(ids); + demoRepository.pageSort(PageRequest.of(1, 10), ids); + + Demo newDemo1 = demoRepository.getReferenceById(demo1.getId()); + Demo newDemo2 = demoRepository.getReferenceById(demo2.getId()); + + assertEquals(newDemo2.getSort(), 1); + assertEquals(newDemo1.getSort(), 0); + } } diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java index a39afa5d..4de36433 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java @@ -1,5 +1,6 @@ package com.codingapi.springboot.fast.entity; +import com.codingapi.springboot.fast.sort.ISort; import lombok.Getter; import lombok.Setter; @@ -10,10 +11,13 @@ @Getter @Entity @Table(name = "t_demo") -public class Demo { +public class Demo implements ISort { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; + + private Integer sort; } diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/DemoRepository.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/DemoRepository.java index 43b36280..9f5c76af 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/DemoRepository.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/DemoRepository.java @@ -2,7 +2,8 @@ import com.codingapi.springboot.fast.entity.Demo; import com.codingapi.springboot.fast.query.FastRepository; +import com.codingapi.springboot.fast.sort.SortRepository; -public interface DemoRepository extends FastRepository { +public interface DemoRepository extends FastRepository, SortRepository { } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index 42e71cef..a8cdfa7d 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -1,6 +1,5 @@ package com.codingapi.springboot.framework.dto.request; -import javax.servlet.http.HttpServletRequest; import lombok.Getter; import lombok.Setter; import org.springframework.data.domain.Pageable; @@ -9,6 +8,7 @@ import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +import javax.servlet.http.HttpServletRequest; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; @@ -32,7 +32,7 @@ public PageRequest(int current, int pageSize, Sort sort) { super(current > 0 ? current-- : 0, pageSize, sort); this.current = current; this.pageSize = pageSize; - this.pageRequest = PageRequest.of(current, pageSize, sort); + this.pageRequest = org.springframework.data.domain.PageRequest.of(current, pageSize, sort); try { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); @@ -251,18 +251,18 @@ public boolean isLessThanEqual() { public Object getFilterValue(Class clazz) { Object val = value[0]; - if(val instanceof String) { - if(clazz == Integer.class) { - return Integer.parseInt((String)val); + if (val instanceof String) { + if (clazz == Integer.class) { + return Integer.parseInt((String) val); } - if(clazz == Long.class) { - return Long.parseLong((String)val); + if (clazz == Long.class) { + return Long.parseLong((String) val); } - if(clazz == Double.class) { - return Double.parseDouble((String)val); + if (clazz == Double.class) { + return Double.parseDouble((String) val); } - if(clazz == Float.class) { - return Float.parseFloat((String)val); + if (clazz == Float.class) { + return Float.parseFloat((String) val); } } return value[0]; @@ -288,4 +288,13 @@ public enum FilterRelation { GREATER_THAN_EQUAL, LESS_THAN_EQUAL, } + + + public static PageRequest of(int page, int size) { + return new PageRequest(page, size, Sort.unsorted()); + } + + public static PageRequest of(int page, int size, Sort sort) { + return new PageRequest(page, size, sort); + } } \ No newline at end of file From 5eabfdaef22bff821707640abff1804a628c71f5 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 11 Oct 2023 22:49:02 +0800 Subject: [PATCH 005/129] fix version --- .../springboot/security/controller/VersionController.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/controller/VersionController.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/controller/VersionController.java index 7d2385a8..03e8445d 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/controller/VersionController.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/controller/VersionController.java @@ -1,5 +1,6 @@ package com.codingapi.springboot.security.controller; +import com.codingapi.springboot.framework.dto.response.SingleResponse; import lombok.AllArgsConstructor; import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.GetMapping; @@ -14,7 +15,7 @@ public class VersionController { private final Environment env; @GetMapping("/version") - public String version(){ - return env.getProperty("application.version","-"); + public SingleResponse version() { + return SingleResponse.of(env.getProperty("application.version", "-")); } } From 8302e6471f6c4b96ffd73fdba9e01e149b2f9a90 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Thu, 26 Oct 2023 23:54:55 +0800 Subject: [PATCH 006/129] add or search --- .../springboot/fast/query/QueryRequest.java | 192 +++++++++++------- .../springboot/fast/DemoRepositoryTest.java | 20 ++ .../framework/dto/request/PageRequest.java | 14 ++ 3 files changed, 149 insertions(+), 77 deletions(-) diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java index 32056ce4..17ab2575 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java @@ -1,13 +1,13 @@ package com.codingapi.springboot.fast.query; import com.codingapi.springboot.framework.dto.request.PageRequest; +import org.springframework.beans.BeanUtils; +import org.springframework.data.domain.Example; + import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.Order; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; -import org.springframework.beans.BeanUtils; -import org.springframework.data.domain.Example; - import java.beans.PropertyDescriptor; import java.util.ArrayList; import java.util.Date; @@ -48,6 +48,16 @@ public Example getExample() { } + private List getClazzProperties() { + List properties = new ArrayList<>(); + PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz); + for (PropertyDescriptor descriptor : descriptors) { + properties.add(descriptor.getName()); + } + return properties; + } + + public List getOrder(Root root, CriteriaBuilder criteriaBuilder) { List orderList = new ArrayList<>(); request.getSort().forEach(sort -> { @@ -62,82 +72,110 @@ public List getOrder(Root root, CriteriaBuilder criteriaBuilder) { public List getPredicate(Root root, CriteriaBuilder criteriaBuilder) { List predicates = new ArrayList<>(); + List properties = getClazzProperties(); for (String key : request.getFilters().keySet()) { PageRequest.Filter filter = request.getFilters().get(key); - if (filter.isEqual()) { - predicates.add(criteriaBuilder.equal(root.get(key), filter.getValue()[0])); - } - - if (filter.isLike()) { - String matchValue = (String) filter.getValue()[0]; - predicates.add(criteriaBuilder.like(root.get(key), "%" + matchValue + "%")); - } - - if (filter.isBetween()) { - Object value1 = filter.getValue()[0]; - Object value2 = filter.getValue()[2]; - if (value1 instanceof Integer && value2 instanceof Integer) { - predicates.add(criteriaBuilder.between(root.get(key), (Integer) value1, (Integer) value2)); - } - - if (value1 instanceof Long && value2 instanceof Long) { - predicates.add(criteriaBuilder.between(root.get(key), (Long) value1, (Long) value2)); - } - - if (value1 instanceof Date && value2 instanceof Date) { - predicates.add(criteriaBuilder.between(root.get(key), (Date) value1, (Date) value2)); - } - } - - if (filter.isGreaterThan()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - predicates.add(criteriaBuilder.greaterThan(root.get(key), (Integer) value)); - } - if (value instanceof Long) { - predicates.add(criteriaBuilder.greaterThan(root.get(key), (Long) value)); - } - if (value instanceof Date) { - predicates.add(criteriaBuilder.greaterThan(root.get(key), (Date) value)); - } - } - - if (filter.isGreaterThanEqual()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Integer) value)); - } - if (value instanceof Long) { - predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Long) value)); - } - if (value instanceof Date) { - predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Date) value)); - } - } - - if (filter.isLessThan()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - predicates.add(criteriaBuilder.lessThan(root.get(key), (Integer) value)); - } - if (value instanceof Long) { - predicates.add(criteriaBuilder.lessThan(root.get(key), (Long) value)); - } - if (value instanceof Date) { - predicates.add(criteriaBuilder.lessThan(root.get(key), (Date) value)); - } - } - - if (filter.isLessThanEqual()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Integer) value)); - } - if (value instanceof Long) { - predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Long) value)); - } - if (value instanceof Date) { - predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Date) value)); + if (filter.isOr() || properties.contains(key)) { + if (filter.isEqual()) { + predicates.add(criteriaBuilder.equal(root.get(key), filter.getValue()[0])); + } + + if (filter.isLike()) { + String matchValue = (String) filter.getValue()[0]; + predicates.add(criteriaBuilder.like(root.get(key), "%" + matchValue + "%")); + } + + if (filter.isBetween()) { + Object value1 = filter.getValue()[0]; + Object value2 = filter.getValue()[2]; + if (value1 instanceof Integer && value2 instanceof Integer) { + predicates.add(criteriaBuilder.between(root.get(key), (Integer) value1, (Integer) value2)); + } + + if (value1 instanceof Long && value2 instanceof Long) { + predicates.add(criteriaBuilder.between(root.get(key), (Long) value1, (Long) value2)); + } + + if (value1 instanceof Date && value2 instanceof Date) { + predicates.add(criteriaBuilder.between(root.get(key), (Date) value1, (Date) value2)); + } + } + + if (filter.isGreaterThan()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + predicates.add(criteriaBuilder.greaterThan(root.get(key), (Integer) value)); + } + if (value instanceof Long) { + predicates.add(criteriaBuilder.greaterThan(root.get(key), (Long) value)); + } + if (value instanceof Date) { + predicates.add(criteriaBuilder.greaterThan(root.get(key), (Date) value)); + } + } + + if (filter.isGreaterThanEqual()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Integer) value)); + } + if (value instanceof Long) { + predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Long) value)); + } + if (value instanceof Date) { + predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Date) value)); + } + } + + if (filter.isLessThan()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + predicates.add(criteriaBuilder.lessThan(root.get(key), (Integer) value)); + } + if (value instanceof Long) { + predicates.add(criteriaBuilder.lessThan(root.get(key), (Long) value)); + } + if (value instanceof Date) { + predicates.add(criteriaBuilder.lessThan(root.get(key), (Date) value)); + } + } + + if (filter.isLessThanEqual()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Integer) value)); + } + if (value instanceof Long) { + predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Long) value)); + } + if (value instanceof Date) { + predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Date) value)); + } + } + + if (filter.isIn()) { + Object[] value = filter.getValue(); + predicates.add(criteriaBuilder.in(root.get(key)).value(value)); + } + + if (filter.isOr()) { + if(key.equals("OR")) { + Object[] value = filter.getValue(); + + // 创建Predicate的列表,用于收集所有的OR条件 + List orPredicates = new ArrayList<>(); + + // 循环遍历value数组,每两个为一组 + for (int i = 0; i < value.length; i += 2) { + orPredicates.add(criteriaBuilder.equal(root.get((String) value[i]), value[i + 1])); + } + + // 使用or方法连接所有的Predicate + predicates.add(criteriaBuilder.or(orPredicates.toArray(new Predicate[0]))); + }else{ + Object[] value = filter.getValue(); + predicates.add(criteriaBuilder.equal(root.get(key), value[0])); + } } } } diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index c1e74ebb..5ba19548 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -74,6 +74,26 @@ void pageRequest() { assertEquals(1, page.getTotalElements()); } + @Test + void pageRequestOr() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + PageRequest request = new PageRequest(); + request.setCurrent(1); + request.setPageSize(10); + request.addOrFilters("name", "%2%","id","1"); + + Page page = demoRepository.pageRequest(request); + assertEquals(1, page.getTotalElements()); + } + @Test void dynamicListQuery() { diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index a8cdfa7d..312a8dbe 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -205,6 +205,15 @@ public PageRequest addFilter(String key, Object... value) { return this.addFilter(key, FilterRelation.EUQAL, value); } + public PageRequest addOrFilters(Object... value) { + // 检查value数组是否为偶数长度,因为我们需要成对处理它 + if (value.length % 2 != 0) { + throw new IllegalArgumentException("Invalid number of elements in value array."); + } + + return this.addFilter("OR", FilterRelation.OR, value); + } + public boolean hasFilter() { return !this.filters.isEmpty(); } @@ -233,6 +242,10 @@ public boolean isIn() { return relation == FilterRelation.IN; } + public boolean isOr() { + return relation == FilterRelation.OR; + } + public boolean isGreaterThan() { return relation == FilterRelation.GREATER_THAN; } @@ -287,6 +300,7 @@ public enum FilterRelation { LESS_THAN, GREATER_THAN_EQUAL, LESS_THAN_EQUAL, + OR, } From a037cddfc509b932d1d9cd1257b41d21c5bd9bf2 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Fri, 27 Oct 2023 17:36:03 +0800 Subject: [PATCH 007/129] add AuthenticationTokenFilter --- .../security/AutoConfiguration.java | 38 +++++++++++++++---- .../configurer/HttpSecurityConfigurer.java | 4 +- .../filter/AuthenticationTokenFilter.java | 12 ++++++ .../filter/MyAuthenticationFilter.java | 5 ++- .../security/filter/MyLoginFilter.java | 4 +- .../security/filter/SecurityLoginHandler.java | 5 ++- 6 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java index 7587aaa0..fb557e55 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java @@ -2,8 +2,10 @@ import com.codingapi.springboot.security.configurer.HttpSecurityConfigurer; import com.codingapi.springboot.security.controller.VersionController; +import com.codingapi.springboot.security.dto.request.LoginRequest; import com.codingapi.springboot.security.filter.*; import com.codingapi.springboot.security.jwt.Jwt; +import com.codingapi.springboot.security.jwt.Token; import com.codingapi.springboot.security.properties.SecurityJwtProperties; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -24,6 +26,9 @@ import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + @Configuration @EnableWebSecurity public class AutoConfiguration { @@ -53,28 +58,45 @@ public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } + @Bean + @ConditionalOnMissingBean + public AuthenticationTokenFilter authenticationTokenFilter() { + return (request, response, chain) -> { + + }; + } + @Bean @ConditionalOnMissingBean - public SecurityLoginHandler securityLoginHandler(){ - return (request, response, handler) -> { + public SecurityLoginHandler securityLoginHandler() { + return new SecurityLoginHandler() { + @Override + public void preHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest handler) throws Exception { + + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest handler, Token token) { + + } }; } @Bean @ConditionalOnMissingBean - public SecurityFilterChain filterChain(HttpSecurity security, Jwt jwt,SecurityLoginHandler loginHandler, - SecurityJwtProperties properties) throws Exception { + public SecurityFilterChain filterChain(HttpSecurity security, Jwt jwt, SecurityLoginHandler loginHandler, + SecurityJwtProperties properties, AuthenticationTokenFilter authenticationTokenFilter) throws Exception { //disable basic auth security.httpBasic().disable(); //before add addCorsMappings to enable cors. security.cors(); - if(properties.isDisableCsrf() ){ + if (properties.isDisableCsrf()) { security.csrf().disable(); } - security.apply(new HttpSecurityConfigurer(jwt,loginHandler,properties)); + security.apply(new HttpSecurityConfigurer(jwt, loginHandler, properties, authenticationTokenFilter)); security .exceptionHandling() .authenticationEntryPoint(new MyUnAuthenticationEntryPoint()) @@ -125,7 +147,7 @@ public WebMvcConfigurer corsConfigurer(SecurityJwtProperties securityJwtProperti return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { - if(securityJwtProperties.isDisableCors()) { + if (securityJwtProperties.isDisableCors()) { registry.addMapping("/**") .allowedHeaders("*") .allowedMethods("*") @@ -149,7 +171,7 @@ public SecurityJwtProperties securityJwtProperties() { @Bean @ConditionalOnMissingBean - public VersionController versionController(Environment environment){ + public VersionController versionController(Environment environment) { return new VersionController(environment); } diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java index d46a3a0b..c95ec34e 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java @@ -1,5 +1,6 @@ package com.codingapi.springboot.security.configurer; +import com.codingapi.springboot.security.filter.AuthenticationTokenFilter; import com.codingapi.springboot.security.filter.MyAuthenticationFilter; import com.codingapi.springboot.security.filter.MyLoginFilter; import com.codingapi.springboot.security.filter.SecurityLoginHandler; @@ -17,11 +18,12 @@ public class HttpSecurityConfigurer extends AbstractHttpConfigurer Date: Sat, 28 Oct 2023 00:15:36 +0800 Subject: [PATCH 008/129] fix Filter --- .../springboot/fast/query/QueryRequest.java | 228 +++++++++--------- .../springboot/fast/DemoRepositoryTest.java | 11 +- .../framework/dto/request/Filter.java | 96 ++++++++ .../framework/dto/request/PageRequest.java | 161 ++----------- .../framework/dto/request/Relation.java | 13 + .../framework/dto/request/RequestFilter.java | 95 ++++++++ 6 files changed, 346 insertions(+), 258 deletions(-) create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java index 17ab2575..ff794568 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java @@ -1,13 +1,16 @@ package com.codingapi.springboot.fast.query; -import com.codingapi.springboot.framework.dto.request.PageRequest; -import org.springframework.beans.BeanUtils; -import org.springframework.data.domain.Example; +import com.codingapi.springboot.framework.dto.request.Filter; +import com.codingapi.springboot.framework.dto.request.PageRequest; +import com.codingapi.springboot.framework.dto.request.RequestFilter; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.Order; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; +import org.springframework.beans.BeanUtils; +import org.springframework.data.domain.Example; + import java.beans.PropertyDescriptor; import java.util.ArrayList; import java.util.Date; @@ -24,7 +27,8 @@ public QueryRequest(PageRequest request, Class clazz) { } public Example getExample() { - if (!request.hasFilter()) { + RequestFilter requestFilter = request.getRequestFilter(); + if (!requestFilter.hasFilter()) { return null; } Object entity = null; @@ -36,7 +40,7 @@ public Example getExample() { PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz); for (PropertyDescriptor descriptor : descriptors) { String name = descriptor.getName(); - PageRequest.Filter value = request.getFilters().get(name); + Filter value = requestFilter.getFilter(name); if (value != null) { try { descriptor.getWriteMethod().invoke(entity, value.getFilterValue(descriptor.getPropertyType())); @@ -70,116 +74,120 @@ public List getOrder(Root root, CriteriaBuilder criteriaBuilder) { return orderList; } + + private Predicate toPredicate(Filter filter, CriteriaBuilder criteriaBuilder, Root root, List properties) { + String key = filter.getKey(); + if (filter.isOr() || properties.contains(key)) { + + if (filter.isEqual()) { + return criteriaBuilder.equal(root.get(key), filter.getValue()[0]); + } + + if (filter.isLike()) { + String matchValue = (String) filter.getValue()[0]; + return criteriaBuilder.like(root.get(key), "%" + matchValue + "%"); + } + + if (filter.isBetween()) { + Object value1 = filter.getValue()[0]; + Object value2 = filter.getValue()[2]; + if (value1 instanceof Integer && value2 instanceof Integer) { + return criteriaBuilder.between(root.get(key), (Integer) value1, (Integer) value2); + } + + if (value1 instanceof Long && value2 instanceof Long) { + return criteriaBuilder.between(root.get(key), (Long) value1, (Long) value2); + } + + if (value1 instanceof Date && value2 instanceof Date) { + return criteriaBuilder.between(root.get(key), (Date) value1, (Date) value2); + } + } + + if (filter.isGreaterThan()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + return criteriaBuilder.greaterThan(root.get(key), (Integer) value); + } + if (value instanceof Long) { + return criteriaBuilder.greaterThan(root.get(key), (Long) value); + } + if (value instanceof Date) { + return criteriaBuilder.greaterThan(root.get(key), (Date) value); + } + } + + if (filter.isGreaterThanEqual()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + return criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Integer) value); + } + if (value instanceof Long) { + return criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Long) value); + } + if (value instanceof Date) { + return criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Date) value); + } + } + + if (filter.isLessThan()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + return criteriaBuilder.lessThan(root.get(key), (Integer) value); + } + if (value instanceof Long) { + return criteriaBuilder.lessThan(root.get(key), (Long) value); + } + if (value instanceof Date) { + return criteriaBuilder.lessThan(root.get(key), (Date) value); + } + } + + if (filter.isLessThanEqual()) { + Object value = filter.getValue()[0]; + if (value instanceof Integer) { + return criteriaBuilder.lessThanOrEqualTo(root.get(key), (Integer) value); + } + if (value instanceof Long) { + return criteriaBuilder.lessThanOrEqualTo(root.get(key), (Long) value); + } + if (value instanceof Date) { + return criteriaBuilder.lessThanOrEqualTo(root.get(key), (Date) value); + } + } + + if (filter.isIn()) { + Object[] value = filter.getValue(); + CriteriaBuilder.In in = criteriaBuilder.in(root.get(key)); + for (Object item : value) { + in.value(item); + } + return in; + } + + if (filter.isOr()) { + Filter[] orFilters = (Filter[]) filter.getValue(); + List orPredicates = new ArrayList<>(); + for (Filter orFilter : orFilters) { + orPredicates.add(toPredicate(orFilter, criteriaBuilder, root, properties)); + } + return criteriaBuilder.or(orPredicates.toArray(new Predicate[0])); + } + } + return null; + } + + public List getPredicate(Root root, CriteriaBuilder criteriaBuilder) { List predicates = new ArrayList<>(); List properties = getClazzProperties(); - for (String key : request.getFilters().keySet()) { - PageRequest.Filter filter = request.getFilters().get(key); - if (filter.isOr() || properties.contains(key)) { - if (filter.isEqual()) { - predicates.add(criteriaBuilder.equal(root.get(key), filter.getValue()[0])); - } - - if (filter.isLike()) { - String matchValue = (String) filter.getValue()[0]; - predicates.add(criteriaBuilder.like(root.get(key), "%" + matchValue + "%")); - } - - if (filter.isBetween()) { - Object value1 = filter.getValue()[0]; - Object value2 = filter.getValue()[2]; - if (value1 instanceof Integer && value2 instanceof Integer) { - predicates.add(criteriaBuilder.between(root.get(key), (Integer) value1, (Integer) value2)); - } - - if (value1 instanceof Long && value2 instanceof Long) { - predicates.add(criteriaBuilder.between(root.get(key), (Long) value1, (Long) value2)); - } - - if (value1 instanceof Date && value2 instanceof Date) { - predicates.add(criteriaBuilder.between(root.get(key), (Date) value1, (Date) value2)); - } - } - - if (filter.isGreaterThan()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - predicates.add(criteriaBuilder.greaterThan(root.get(key), (Integer) value)); - } - if (value instanceof Long) { - predicates.add(criteriaBuilder.greaterThan(root.get(key), (Long) value)); - } - if (value instanceof Date) { - predicates.add(criteriaBuilder.greaterThan(root.get(key), (Date) value)); - } - } - - if (filter.isGreaterThanEqual()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Integer) value)); - } - if (value instanceof Long) { - predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Long) value)); - } - if (value instanceof Date) { - predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Date) value)); - } - } - - if (filter.isLessThan()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - predicates.add(criteriaBuilder.lessThan(root.get(key), (Integer) value)); - } - if (value instanceof Long) { - predicates.add(criteriaBuilder.lessThan(root.get(key), (Long) value)); - } - if (value instanceof Date) { - predicates.add(criteriaBuilder.lessThan(root.get(key), (Date) value)); - } - } - - if (filter.isLessThanEqual()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Integer) value)); - } - if (value instanceof Long) { - predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Long) value)); - } - if (value instanceof Date) { - predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(key), (Date) value)); - } - } - - if (filter.isIn()) { - Object[] value = filter.getValue(); - predicates.add(criteriaBuilder.in(root.get(key)).value(value)); - } - - if (filter.isOr()) { - if(key.equals("OR")) { - Object[] value = filter.getValue(); - - // 创建Predicate的列表,用于收集所有的OR条件 - List orPredicates = new ArrayList<>(); - - // 循环遍历value数组,每两个为一组 - for (int i = 0; i < value.length; i += 2) { - orPredicates.add(criteriaBuilder.equal(root.get((String) value[i]), value[i + 1])); - } - - // 使用or方法连接所有的Predicate - predicates.add(criteriaBuilder.or(orPredicates.toArray(new Predicate[0]))); - }else{ - Object[] value = filter.getValue(); - predicates.add(criteriaBuilder.equal(root.get(key), value[0])); - } - } + RequestFilter requestFilter = request.getRequestFilter(); + for (Filter filter : requestFilter.getFilters()) { + Predicate predicate = toPredicate(filter, criteriaBuilder, root, properties); + if (predicate != null) { + predicates.add(predicate); } } - return predicates; } } \ No newline at end of file diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index 5ba19548..2cf69b91 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -2,7 +2,9 @@ import com.codingapi.springboot.fast.entity.Demo; import com.codingapi.springboot.fast.repository.DemoRepository; +import com.codingapi.springboot.framework.dto.request.Filter; import com.codingapi.springboot.framework.dto.request.PageRequest; +import com.codingapi.springboot.framework.dto.request.Relation; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -68,14 +70,14 @@ void pageRequest() { PageRequest request = new PageRequest(); request.setCurrent(1); request.setPageSize(10); - request.addFilter("name", PageRequest.FilterRelation.LIKE, "%2%"); + request.addFilter("name", Relation.LIKE, "%2%"); Page page = demoRepository.pageRequest(request); assertEquals(1, page.getTotalElements()); } @Test - void pageRequestOr() { + void customSearchOr() { demoRepository.deleteAll(); Demo demo1 = new Demo(); demo1.setName("123"); @@ -88,10 +90,11 @@ void pageRequestOr() { PageRequest request = new PageRequest(); request.setCurrent(1); request.setPageSize(10); - request.addOrFilters("name", "%2%","id","1"); + + request.orFilters(Filter.as("name", Relation.LIKE, "%2%"), Filter.as("id", Relation.IN, 1, 2, 3)); Page page = demoRepository.pageRequest(request); - assertEquals(1, page.getTotalElements()); + assertEquals(2, page.getTotalElements()); } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java new file mode 100644 index 00000000..eb143b60 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java @@ -0,0 +1,96 @@ +package com.codingapi.springboot.framework.dto.request; + + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class Filter { + + private String key; + private Object[] value; + private Relation relation; + + public Filter(String key, Relation relation, Object... value) { + this.key = key; + this.value = value; + this.relation = relation; + } + + public Filter(String key, Object... value) { + this(key, Relation.EQUAL, value); + } + + public Filter(Filter... value) { + this(null, null, value); + } + + public static Filter as(String key, Relation relation, Object... value) { + return new Filter(key, relation, value); + } + + public static Filter as(String key, Object... value) { + return new Filter(key, value); + } + + public static Filter as(Filter... value) { + return new Filter(value); + } + + public boolean isEqual() { + return relation == Relation.EQUAL; + } + + public boolean isLike() { + return relation == Relation.LIKE; + } + + public boolean isBetween() { + return relation == Relation.BETWEEN; + } + + public boolean isIn() { + return relation == Relation.IN; + } + + public boolean isOr() { + return value != null && value.length > 0 && value[0] instanceof Filter; + } + + public boolean isGreaterThan() { + return relation == Relation.GREATER_THAN; + } + + public boolean isLessThan() { + return relation == Relation.LESS_THAN; + } + + public boolean isGreaterThanEqual() { + return relation == Relation.GREATER_THAN_EQUAL; + } + + public boolean isLessThanEqual() { + return relation == Relation.LESS_THAN_EQUAL; + } + + public Object getFilterValue(Class clazz) { + Object val = value[0]; + if (val instanceof String) { + if (clazz == Integer.class) { + return Integer.parseInt((String) val); + } + if (clazz == Long.class) { + return Long.parseLong((String) val); + } + if (clazz == Double.class) { + return Double.parseDouble((String) val); + } + if (clazz == Float.class) { + return Float.parseFloat((String) val); + } + } + return value[0]; + } + +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index 312a8dbe..65257362 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -1,17 +1,12 @@ package com.codingapi.springboot.framework.dto.request; +import javax.servlet.http.HttpServletRequest; import lombok.Getter; -import lombok.Setter; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import javax.servlet.http.HttpServletRequest; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; import java.util.Optional; public class PageRequest extends org.springframework.data.domain.PageRequest { @@ -21,7 +16,7 @@ public class PageRequest extends org.springframework.data.domain.PageRequest { private int pageSize; @Getter - private final Map filters = new HashMap<>(); + private final RequestFilter requestFilter = new RequestFilter(); @Getter private HttpServletRequest servletRequest; @@ -37,23 +32,12 @@ public PageRequest(int current, int pageSize, Sort sort) { try { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); this.servletRequest = attributes.getRequest(); - this.syncParameter(); + requestFilter.syncParameter(servletRequest); } catch (Exception e) { } } - private void syncParameter() { - Enumeration enumeration = servletRequest.getParameterNames(); - while (enumeration.hasMoreElements()) { - String key = enumeration.nextElement(); - String value = servletRequest.getParameter(key); - if (StringUtils.hasText(value)) { - addFilter(key, value); - } - } - } - public PageRequest() { this(0, 20, Sort.unsorted()); } @@ -80,43 +64,25 @@ public int getIntParameter(String key, int defaultValue) { return result == null ? defaultValue : Integer.parseInt(result); } - public String getStringFilter(String key) { - Filter filter = (Filter) filters.get(key); - if (filter != null) { - return (String) filter.getValue()[0]; - } - return null; + return requestFilter.getStringFilter(key); } public String getStringFilter(String key, String defaultValue) { - String value = getStringFilter(key); - if (!StringUtils.hasText(value)) { - return defaultValue; - } - return value; + return requestFilter.getStringFilter(key, defaultValue); } public int getIntFilter(String key) { - Filter filter = (Filter) filters.get(key); - if (filter != null) { - String value = (String) filter.getValue()[0]; - if (StringUtils.hasText(value)) { - return Integer.parseInt(value); - } - return 0; - } - return 0; + return requestFilter.getIntFilter(key); } public int getIntFilter(String key, int defaultValue) { - int value = getIntFilter(key); - if (value == 0) { - return defaultValue; - } - return value; + return requestFilter.getIntFilter(key, defaultValue); } + public boolean hasFilter() { + return requestFilter.hasFilter(); + } @Override public int getPageSize() { @@ -196,114 +162,21 @@ public void addSort(Sort sort) { } } - public PageRequest addFilter(String key, FilterRelation relation, Object... value) { - putFilter(key, relation, value); + public PageRequest addFilter(String key, Relation relation, Object... value) { + requestFilter.addFilter(key, relation, value); return this; } public PageRequest addFilter(String key, Object... value) { - return this.addFilter(key, FilterRelation.EUQAL, value); - } - - public PageRequest addOrFilters(Object... value) { - // 检查value数组是否为偶数长度,因为我们需要成对处理它 - if (value.length % 2 != 0) { - throw new IllegalArgumentException("Invalid number of elements in value array."); - } - - return this.addFilter("OR", FilterRelation.OR, value); - } - - public boolean hasFilter() { - return !this.filters.isEmpty(); - } - - @Setter - @Getter - public static class Filter { - private String key; - private Object[] value; - - private FilterRelation relation; - - public boolean isEqual() { - return relation == FilterRelation.EUQAL; - } - - public boolean isLike() { - return relation == FilterRelation.LIKE; - } - - public boolean isBetween() { - return relation == FilterRelation.BETWEEN; - } - - public boolean isIn() { - return relation == FilterRelation.IN; - } - - public boolean isOr() { - return relation == FilterRelation.OR; - } - - public boolean isGreaterThan() { - return relation == FilterRelation.GREATER_THAN; - } - - public boolean isLessThan() { - return relation == FilterRelation.LESS_THAN; - } - - public boolean isGreaterThanEqual() { - return relation == FilterRelation.GREATER_THAN_EQUAL; - } - - public boolean isLessThanEqual() { - return relation == FilterRelation.LESS_THAN_EQUAL; - } - - public Object getFilterValue(Class clazz) { - Object val = value[0]; - if (val instanceof String) { - if (clazz == Integer.class) { - return Integer.parseInt((String) val); - } - if (clazz == Long.class) { - return Long.parseLong((String) val); - } - if (clazz == Double.class) { - return Double.parseDouble((String) val); - } - if (clazz == Float.class) { - return Float.parseFloat((String) val); - } - } - return value[0]; - } - - } - - private void putFilter(String key, FilterRelation relation, Object... val) { - Filter filter = new Filter(); - filter.setKey(key); - filter.setValue(val); - filter.setRelation(relation); - this.filters.put(key, filter); + requestFilter.addFilter(key, value); + return this; } - public enum FilterRelation { - EUQAL, - LIKE, - BETWEEN, - IN, - GREATER_THAN, - LESS_THAN, - GREATER_THAN_EQUAL, - LESS_THAN_EQUAL, - OR, + public PageRequest orFilters(Filter... filters) { + requestFilter.orFilters(filters); + return this; } - public static PageRequest of(int page, int size) { return new PageRequest(page, size, Sort.unsorted()); } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java new file mode 100644 index 00000000..a5b3eaa0 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java @@ -0,0 +1,13 @@ +package com.codingapi.springboot.framework.dto.request; + +public enum Relation { + + EQUAL, + LIKE, + BETWEEN, + IN, + GREATER_THAN, + LESS_THAN, + GREATER_THAN_EQUAL, + LESS_THAN_EQUAL, +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java new file mode 100644 index 00000000..972b8823 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java @@ -0,0 +1,95 @@ +package com.codingapi.springboot.framework.dto.request; + + +import javax.servlet.http.HttpServletRequest; +import org.springframework.util.StringUtils; + +import java.util.*; + +public class RequestFilter { + + private final Map filterMap = new HashMap<>(); + private final List filterList = new ArrayList<>(); + + public RequestFilter addFilter(String key, Relation relation, Object... value) { + this.pushFilter(new Filter(key, relation, value)); + return this; + } + + public RequestFilter addFilter(String key, Object... value) { + this.pushFilter(new Filter(key, value)); + return this; + } + + public RequestFilter orFilters(Filter... value) { + this.pushFilter(new Filter(value)); + return this; + } + + public List getFilters() { + return filterList; + } + + public void pushFilter(Filter filter) { + filterList.add(filter); + filterMap.put(filter.getKey(), filter); + } + + public void syncParameter(HttpServletRequest servletRequest) { + Enumeration enumeration = servletRequest.getParameterNames(); + while (enumeration.hasMoreElements()) { + String key = enumeration.nextElement(); + String value = servletRequest.getParameter(key); + if (StringUtils.hasText(value)) { + addFilter(key, value); + } + } + } + + + public String getStringFilter(String key) { + Filter filter = filterMap.get(key); + if (filter != null) { + return (String) filter.getValue()[0]; + } + return null; + } + + public String getStringFilter(String key, String defaultValue) { + String value = getStringFilter(key); + if (!StringUtils.hasText(value)) { + return defaultValue; + } + return value; + } + + public int getIntFilter(String key) { + Filter filter = filterMap.get(key); + if (filter != null) { + String value = (String) filter.getValue()[0]; + if (StringUtils.hasText(value)) { + return Integer.parseInt(value); + } + return 0; + } + return 0; + } + + public int getIntFilter(String key, int defaultValue) { + int value = getIntFilter(key); + if (value == 0) { + return defaultValue; + } + return value; + } + + + public boolean hasFilter() { + return !this.filterMap.isEmpty(); + } + + + public Filter getFilter(String name) { + return this.filterMap.get(name); + } +} From f2777e159df0d3a92671b2c89aac51e966da5b1f Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 28 Oct 2023 00:31:23 +0800 Subject: [PATCH 009/129] fix Filter --- .../codingapi/springboot/fast/query/QueryRequest.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java index ff794568..0575c991 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java @@ -4,13 +4,13 @@ import com.codingapi.springboot.framework.dto.request.Filter; import com.codingapi.springboot.framework.dto.request.PageRequest; import com.codingapi.springboot.framework.dto.request.RequestFilter; +import org.springframework.beans.BeanUtils; +import org.springframework.data.domain.Example; + import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.Order; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; -import org.springframework.beans.BeanUtils; -import org.springframework.data.domain.Example; - import java.beans.PropertyDescriptor; import java.util.ArrayList; import java.util.Date; @@ -169,7 +169,10 @@ private Predicate toPredicate(Filter filter, CriteriaBuilder criteriaBuilder Filter[] orFilters = (Filter[]) filter.getValue(); List orPredicates = new ArrayList<>(); for (Filter orFilter : orFilters) { - orPredicates.add(toPredicate(orFilter, criteriaBuilder, root, properties)); + Predicate predicate = toPredicate(orFilter, criteriaBuilder, root, properties); + if (predicate != null) { + orPredicates.add(predicate); + } } return criteriaBuilder.or(orPredicates.toArray(new Predicate[0])); } From 335736268c9a285c4d564c695b02ee6438ff70c3 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 28 Oct 2023 01:13:59 +0800 Subject: [PATCH 010/129] fix Filter --- .../springboot/fast/query/QueryRequest.java | 16 +++++++++++-- .../springboot/fast/DemoRepositoryTest.java | 23 ++++++++++++++++++- .../framework/dto/request/Filter.java | 23 ++++++++++++++----- .../framework/dto/request/PageRequest.java | 5 ++++ .../framework/dto/request/RequestFilter.java | 9 ++++++-- 5 files changed, 65 insertions(+), 11 deletions(-) diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java index 0575c991..bc906675 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java @@ -77,7 +77,7 @@ public List getOrder(Root root, CriteriaBuilder criteriaBuilder) { private Predicate toPredicate(Filter filter, CriteriaBuilder criteriaBuilder, Root root, List properties) { String key = filter.getKey(); - if (filter.isOr() || properties.contains(key)) { + if (filter.isAddFilters() || filter.isOrFilters() || properties.contains(key)) { if (filter.isEqual()) { return criteriaBuilder.equal(root.get(key), filter.getValue()[0]); @@ -165,7 +165,7 @@ private Predicate toPredicate(Filter filter, CriteriaBuilder criteriaBuilder return in; } - if (filter.isOr()) { + if (filter.isOrFilters()) { Filter[] orFilters = (Filter[]) filter.getValue(); List orPredicates = new ArrayList<>(); for (Filter orFilter : orFilters) { @@ -176,6 +176,18 @@ private Predicate toPredicate(Filter filter, CriteriaBuilder criteriaBuilder } return criteriaBuilder.or(orPredicates.toArray(new Predicate[0])); } + + if (filter.isAddFilters()) { + Filter[] orFilters = (Filter[]) filter.getValue(); + List addPredicates = new ArrayList<>(); + for (Filter orFilter : orFilters) { + Predicate predicate = toPredicate(orFilter, criteriaBuilder, root, properties); + if (predicate != null) { + addPredicates.add(predicate); + } + } + return criteriaBuilder.and(addPredicates.toArray(new Predicate[0])); + } } return null; } diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index 2cf69b91..3296f8b8 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -77,7 +77,7 @@ void pageRequest() { } @Test - void customSearchOr() { + void customSearchOrFilters() { demoRepository.deleteAll(); Demo demo1 = new Demo(); demo1.setName("123"); @@ -97,6 +97,27 @@ void customSearchOr() { assertEquals(2, page.getTotalElements()); } + @Test + void customSearchAddFilters() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + PageRequest request = new PageRequest(); + request.setCurrent(1); + request.setPageSize(10); + +// request.addFilters(Filter.as("id", Relation.IN, 1),Filter.as("id", Relation.IN, 2),Filter.as("id", Relation.IN, 3),Filter.as("id", Relation.IN, 4)); + request.orFilters(Filter.as("name", Relation.LIKE, "%2%"),Filter.and(Filter.as("id", Relation.IN, 1),Filter.as("id", Relation.IN, 2))); + Page page = demoRepository.pageRequest(request); + assertEquals(2, page.getTotalElements()); + } + @Test void dynamicListQuery() { diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java index eb143b60..f6ea8da7 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java @@ -8,6 +8,9 @@ @Getter public class Filter { + public static final String FILTER_OR_KEY = "FILTER_OR_KEY"; + public static final String FILTER_ADD_KEY = "FILTER_ADD_KEY"; + private String key; private Object[] value; private Relation relation; @@ -22,8 +25,8 @@ public Filter(String key, Object... value) { this(key, Relation.EQUAL, value); } - public Filter(Filter... value) { - this(null, null, value); + public Filter(String key, Filter... value) { + this(key, null, value); } public static Filter as(String key, Relation relation, Object... value) { @@ -34,8 +37,12 @@ public static Filter as(String key, Object... value) { return new Filter(key, value); } - public static Filter as(Filter... value) { - return new Filter(value); + public static Filter and(Filter... value) { + return new Filter(FILTER_ADD_KEY, value); + } + + public static Filter or(Filter... value) { + return new Filter(FILTER_OR_KEY, value); } public boolean isEqual() { @@ -54,8 +61,12 @@ public boolean isIn() { return relation == Relation.IN; } - public boolean isOr() { - return value != null && value.length > 0 && value[0] instanceof Filter; + public boolean isOrFilters() { + return FILTER_OR_KEY.equals(key); + } + + public boolean isAddFilters() { + return FILTER_ADD_KEY.equals(key); } public boolean isGreaterThan() { diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index 65257362..923903d8 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -172,6 +172,11 @@ public PageRequest addFilter(String key, Object... value) { return this; } + public PageRequest addFilters(Filter... filters) { + requestFilter.addFilters(filters); + return this; + } + public PageRequest orFilters(Filter... filters) { requestFilter.orFilters(filters); return this; diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java index 972b8823..8fbc2b4b 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java @@ -1,9 +1,9 @@ package com.codingapi.springboot.framework.dto.request; -import javax.servlet.http.HttpServletRequest; import org.springframework.util.StringUtils; +import javax.servlet.http.HttpServletRequest; import java.util.*; public class RequestFilter { @@ -21,8 +21,13 @@ public RequestFilter addFilter(String key, Object... value) { return this; } + public RequestFilter addFilters(Filter... value) { + this.pushFilter(new Filter(Filter.FILTER_ADD_KEY, value)); + return this; + } + public RequestFilter orFilters(Filter... value) { - this.pushFilter(new Filter(value)); + this.pushFilter(new Filter(Filter.FILTER_OR_KEY, value)); return this; } From 268595d731a9bc8dd6def44dbdf823032df89473 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 28 Oct 2023 01:47:47 +0800 Subject: [PATCH 011/129] fix Filter --- .../com/codingapi/springboot/fast/DemoRepositoryTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index 3296f8b8..ac821ffa 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -91,10 +91,10 @@ void customSearchOrFilters() { request.setCurrent(1); request.setPageSize(10); - request.orFilters(Filter.as("name", Relation.LIKE, "%2%"), Filter.as("id", Relation.IN, 1, 2, 3)); + request.orFilters(Filter.and(Filter.as("name", Relation.LIKE, "%2%"),Filter.as("name", Relation.LIKE, "%1%")), Filter.and(Filter.as("id", Relation.IN, 1),Filter.as("id", Relation.IN, 2))); Page page = demoRepository.pageRequest(request); - assertEquals(2, page.getTotalElements()); + assertEquals(1, page.getTotalElements()); } @Test @@ -113,9 +113,9 @@ void customSearchAddFilters() { request.setPageSize(10); // request.addFilters(Filter.as("id", Relation.IN, 1),Filter.as("id", Relation.IN, 2),Filter.as("id", Relation.IN, 3),Filter.as("id", Relation.IN, 4)); - request.orFilters(Filter.as("name", Relation.LIKE, "%2%"),Filter.and(Filter.as("id", Relation.IN, 1),Filter.as("id", Relation.IN, 2))); + request.addFilters(Filter.as("name", Relation.LIKE, "%2%"), Filter.and(Filter.as("id", Relation.IN, 1), Filter.as("id", Relation.IN, 2))); Page page = demoRepository.pageRequest(request); - assertEquals(2, page.getTotalElements()); + assertEquals(0, page.getTotalElements()); } From 65908bd69789ed462f7dc377c9c3b9dd43203aa8 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 28 Oct 2023 12:18:43 +0800 Subject: [PATCH 012/129] update 2.7.2 --- .../com/codingapi/springboot/fast/query/QueryRequest.java | 4 ++-- .../com/codingapi/springboot/fast/DemoRepositoryTest.java | 2 +- .../springboot/framework/dto/request/Filter.java | 8 ++++---- .../springboot/framework/dto/request/PageRequest.java | 4 ++-- .../springboot/framework/dto/request/RequestFilter.java | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java index bc906675..686ac1a8 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java @@ -77,7 +77,7 @@ public List getOrder(Root root, CriteriaBuilder criteriaBuilder) { private Predicate toPredicate(Filter filter, CriteriaBuilder criteriaBuilder, Root root, List properties) { String key = filter.getKey(); - if (filter.isAddFilters() || filter.isOrFilters() || properties.contains(key)) { + if (filter.isAndFilters() || filter.isOrFilters() || properties.contains(key)) { if (filter.isEqual()) { return criteriaBuilder.equal(root.get(key), filter.getValue()[0]); @@ -177,7 +177,7 @@ private Predicate toPredicate(Filter filter, CriteriaBuilder criteriaBuilder return criteriaBuilder.or(orPredicates.toArray(new Predicate[0])); } - if (filter.isAddFilters()) { + if (filter.isAndFilters()) { Filter[] orFilters = (Filter[]) filter.getValue(); List addPredicates = new ArrayList<>(); for (Filter orFilter : orFilters) { diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index ac821ffa..f79cd5f3 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -113,7 +113,7 @@ void customSearchAddFilters() { request.setPageSize(10); // request.addFilters(Filter.as("id", Relation.IN, 1),Filter.as("id", Relation.IN, 2),Filter.as("id", Relation.IN, 3),Filter.as("id", Relation.IN, 4)); - request.addFilters(Filter.as("name", Relation.LIKE, "%2%"), Filter.and(Filter.as("id", Relation.IN, 1), Filter.as("id", Relation.IN, 2))); + request.andFilters(Filter.as("name", Relation.LIKE, "%2%"), Filter.and(Filter.as("id", Relation.IN, 1), Filter.as("id", Relation.IN, 2))); Page page = demoRepository.pageRequest(request); assertEquals(0, page.getTotalElements()); } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java index f6ea8da7..0acb1477 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java @@ -9,7 +9,7 @@ public class Filter { public static final String FILTER_OR_KEY = "FILTER_OR_KEY"; - public static final String FILTER_ADD_KEY = "FILTER_ADD_KEY"; + public static final String FILTER_AND_KEY = "FILTER_AND_KEY"; private String key; private Object[] value; @@ -38,7 +38,7 @@ public static Filter as(String key, Object... value) { } public static Filter and(Filter... value) { - return new Filter(FILTER_ADD_KEY, value); + return new Filter(FILTER_AND_KEY, value); } public static Filter or(Filter... value) { @@ -65,8 +65,8 @@ public boolean isOrFilters() { return FILTER_OR_KEY.equals(key); } - public boolean isAddFilters() { - return FILTER_ADD_KEY.equals(key); + public boolean isAndFilters() { + return FILTER_AND_KEY.equals(key); } public boolean isGreaterThan() { diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index 923903d8..7c0eb2df 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -172,8 +172,8 @@ public PageRequest addFilter(String key, Object... value) { return this; } - public PageRequest addFilters(Filter... filters) { - requestFilter.addFilters(filters); + public PageRequest andFilters(Filter... filters) { + requestFilter.andFilters(filters); return this; } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java index 8fbc2b4b..12e6d6ac 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java @@ -21,8 +21,8 @@ public RequestFilter addFilter(String key, Object... value) { return this; } - public RequestFilter addFilters(Filter... value) { - this.pushFilter(new Filter(Filter.FILTER_ADD_KEY, value)); + public RequestFilter andFilters(Filter... value) { + this.pushFilter(new Filter(Filter.FILTER_AND_KEY, value)); return this; } From 1bd5c1fefde7f1b150da4fa2b9b3ff398263bdb2 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 28 Oct 2023 13:24:58 +0800 Subject: [PATCH 013/129] add wiki --- docs/wiki/springboot-starter-data-fast.md | 29 +++++++++++++++++-- docs/wiki/springboot-starter-security-jwt.md | 20 +++++++++---- .../springboot/fast/DemoRepositoryTest.java | 5 ++-- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/docs/wiki/springboot-starter-data-fast.md b/docs/wiki/springboot-starter-data-fast.md index 154795dc..cd631789 100644 --- a/docs/wiki/springboot-starter-data-fast.md +++ b/docs/wiki/springboot-starter-data-fast.md @@ -64,7 +64,7 @@ public interface DemoRepository extends FastRepository { ``` 动态FastRepository的能力展示 -```java +``` // 重写findAll,通过Example查询 @Test @@ -90,7 +90,7 @@ public interface DemoRepository extends FastRepository { // pageRequest 自定义条件查询 @Test - void pageRequest() { + void pageRequest1() { demoRepository.deleteAll(); Demo demo1 = new Demo(); demo1.setName("123"); @@ -104,10 +104,33 @@ public interface DemoRepository extends FastRepository { request.setCurrent(1); request.setPageSize(10); request.addFilter("name", PageRequest.FilterRelation.LIKE, "%2%"); + //sql: select demo0_.id as id1_0_, demo0_.name as name2_0_, demo0_.sort as sort3_0_ from t_demo demo0_ where demo0_.name like ? limit ? Page page = demoRepository.pageRequest(request); assertEquals(1, page.getTotalElements()); - } + } + + // pageRequest 自定义条件查询 + @Test + void pageRequest2() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + PageRequest request = new PageRequest(); + request.setCurrent(1); + request.setPageSize(10); + request.orFilters(Filter.as("name","123"),Filter.as("name","456")); + //sql: select demo0_.id as id1_0_, demo0_.name as name2_0_, demo0_.sort as sort3_0_ from t_demo demo0_ where demo0_.name=? or demo0_.name=? limit ? + + Page page = demoRepository.pageRequest(request); + assertEquals(1, page.getTotalElements()); + } // 动态sql的List查询 diff --git a/docs/wiki/springboot-starter-security-jwt.md b/docs/wiki/springboot-starter-security-jwt.md index dd984683..d7c71b5b 100644 --- a/docs/wiki/springboot-starter-security-jwt.md +++ b/docs/wiki/springboot-starter-security-jwt.md @@ -51,14 +51,22 @@ security默认的账户密码为admin/admin,可以通过重写UserDetailsServi 也可以通过数据库账户获取账户数据,请自己实现UserDetailsService接口 ## 登录拦截 -可以通过重写SecurityLoginHandler来实现自定义登录拦截 +可以通过重写SecurityLoginHandler来实现自定义登录拦截,preHandle登录前的拦截处理,postHandle登录后的拦截处理 ```java @Bean - public SecurityLoginHandler securityLoginHandler(){ - return (request, response, handler) -> { - //TODO 自定义登录拦截 - }; - } + public SecurityLoginHandler securityLoginHandler() { + return new SecurityLoginHandler() { + @Override + public void preHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest handler) throws Exception { + + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest handler, Token token) { + + } + }; +} ``` ## 获取当前用户 diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index f79cd5f3..bb00452f 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -90,11 +90,10 @@ void customSearchOrFilters() { PageRequest request = new PageRequest(); request.setCurrent(1); request.setPageSize(10); - - request.orFilters(Filter.and(Filter.as("name", Relation.LIKE, "%2%"),Filter.as("name", Relation.LIKE, "%1%")), Filter.and(Filter.as("id", Relation.IN, 1),Filter.as("id", Relation.IN, 2))); + request.orFilters(Filter.as("name","123"),Filter.as("name","456")); Page page = demoRepository.pageRequest(request); - assertEquals(1, page.getTotalElements()); + assertEquals(2, page.getTotalElements()); } @Test From 6a796c854be4edb04c46e78aa89f41b24deb4a5c Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 28 Oct 2023 13:36:26 +0800 Subject: [PATCH 014/129] =?UTF-8?q?add=20=E9=A1=B9=E7=9B=AE=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 149c9aa5..a3ddf406 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,11 @@ 本框架基于springboot为提供领域驱动设计与事件风暴开发落地,提供的范式开源框架。 +## Project Version | 项目版本说明 + +v.2.x 为springboot 2.x版本,使用jdk8版本 +v.3.x 为springboot 3.x版本,使用jdk17版本 + ## Project Modules Description | 项目模块介绍 * springboot-starter | Springboot领域驱动框架 From 380064909c5a554878c4915bdc87160e246beb1b Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Wed, 8 Nov 2023 17:45:20 +0800 Subject: [PATCH 015/129] #29 fix addFilter --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-id-generator/pom.xml | 2 +- springboot-starter-security-jwt/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../springboot/framework/dto/request/RequestFilter.java | 1 + 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index c03da97d..86d6d4bc 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.2 + 2.7.3 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 85efb421..29896644 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.2 + 2.7.3 4.0.0 diff --git a/springboot-starter-id-generator/pom.xml b/springboot-starter-id-generator/pom.xml index 3f3a6a34..8398f703 100644 --- a/springboot-starter-id-generator/pom.xml +++ b/springboot-starter-id-generator/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.2 + 2.7.3 4.0.0 diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index 68c74e24..221e1f0b 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.2 + 2.7.3 springboot-starter-security-jwt diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 74016e37..d82e08b1 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.2 + 2.7.3 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java index 12e6d6ac..5c4cf90e 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java @@ -36,6 +36,7 @@ public List getFilters() { } public void pushFilter(Filter filter) { + filterList.removeIf(item -> item.getKey().equals(filter.getKey())); filterList.add(filter); filterMap.put(filter.getKey(), filter); } From 2b3f970a9b147ad0c323e681a53f84f2e6a0b127 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 8 Nov 2023 21:37:21 +0800 Subject: [PATCH 016/129] fix #29 update 2.7.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 86d6d4bc..c00e92b4 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.16 + 2.7.17 From 8fdb7a1448a6819870b842e80a42fc943888ede0 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 8 Nov 2023 22:58:34 +0800 Subject: [PATCH 017/129] fix #29 update 2.7.4 --- pom.xml | 34 ++++++++++++++----- springboot-starter-data-fast/pom.xml | 2 +- .../fast/dynamic/DynamicRepository.java | 1 + springboot-starter-id-generator/pom.xml | 2 +- springboot-starter-security-jwt/pom.xml | 2 +- .../springboot/security/jwt/Jwt.java | 12 +++---- springboot-starter/pom.xml | 2 +- .../serializable/MapSerializable.java | 3 +- 8 files changed, 39 insertions(+), 19 deletions(-) diff --git a/pom.xml b/pom.xml index c00e92b4..0f2c8d2e 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.3 + 2.7.4 https://github.com/codingapi/springboot-framewrok springboot-parent @@ -27,18 +27,19 @@ 8 3.0.1 3.11.0 - 2.10.3 - 1.6.3 - 1.6 + 3.6.1 + 1.6.13 + 3.1.0 ${project.version} - 2.0.28 - 0.11.5 - 2.11.0 - 1.7 + 2.0.42 + 0.12.3 + 2.15.0 + 1.8.1 0.10.2 0.9.16 1.70 1.2.0 + 2.2 @@ -46,6 +47,17 @@ org.springframework.boot spring-boot-starter + + + org.yaml + snakeyaml + + + + + + org.yaml + snakeyaml @@ -155,6 +167,12 @@ ${commons-dbutils.version} + + org.yaml + snakeyaml + ${org.yaml.snakeyaml.version} + + diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 29896644..dcccfc34 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.3 + 2.7.4 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicRepository.java index fffd31a4..cd50e728 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicRepository.java @@ -9,6 +9,7 @@ import java.util.List; @NoRepositoryBean +@SuppressWarnings("unchecked") public interface DynamicRepository extends JpaRepository { default Class getEntityClass() { diff --git a/springboot-starter-id-generator/pom.xml b/springboot-starter-id-generator/pom.xml index 8398f703..f228fb24 100644 --- a/springboot-starter-id-generator/pom.xml +++ b/springboot-starter-id-generator/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.3 + 2.7.4 4.0.0 diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index 221e1f0b..e1d89429 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.3 + 2.7.4 springboot-starter-security-jwt diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Jwt.java b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Jwt.java index c1b7a2b8..75f93713 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Jwt.java +++ b/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Jwt.java @@ -7,13 +7,13 @@ import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; +import javax.crypto.SecretKey; import java.nio.charset.StandardCharsets; -import java.security.Key; import java.util.List; public class Jwt { - private final Key key; + private final SecretKey key; private final int jwtTime; private final int jwtRestTime; @@ -37,16 +37,16 @@ public Token create(String username, String iv, List authorities){ public Token create(String username, String iv,List authorities,String extra){ Token token = new Token(username, iv,extra, authorities, jwtTime, jwtRestTime); - String jwt = Jwts.builder().setSubject(token.toJson()).signWith(key).compact(); + String jwt = Jwts.builder().subject(token.toJson()).signWith(key).compact(); token.setToken(jwt); return token; } public Token parser(String sign) { try { - Jws jws = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(sign); + Jws jws = Jwts.parser().verifyWith(key).build().parseSignedClaims(sign); if (jws != null) { - String subject = jws.getBody().getSubject(); + String subject = jws.getPayload().getSubject(); return JSONObject.parseObject(subject, Token.class); } throw new LocaleMessageException("token.error", "token失效,请重新登录."); @@ -54,4 +54,4 @@ public Token parser(String sign) { throw new LocaleMessageException("token.error", exp.getMessage()); } } -} +} \ No newline at end of file diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index d82e08b1..ff00567b 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.3 + 2.7.4 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/serializable/MapSerializable.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/serializable/MapSerializable.java index e7f96743..2b40aae7 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/serializable/MapSerializable.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/serializable/MapSerializable.java @@ -1,6 +1,7 @@ package com.codingapi.springboot.framework.serializable; import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson2.JSON; import java.util.Map; @@ -11,6 +12,6 @@ public interface MapSerializable { default Map toMap() { - return (Map) JSONObject.toJSON(this); + return JSON.parseObject(JSONObject.toJSONString(this)); } } From a6c86d42dd9bfb11af6d08404c3876495715eeca Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Thu, 9 Nov 2023 08:42:27 +0800 Subject: [PATCH 018/129] update snakeyaml version 2.2 --- pom.xml | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index 0f2c8d2e..cecd1c03 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 0.9.16 1.70 1.2.0 - 2.2 + 2.2 @@ -47,17 +47,6 @@ org.springframework.boot spring-boot-starter - - - org.yaml - snakeyaml - - - - - - org.yaml - snakeyaml @@ -167,11 +156,6 @@ ${commons-dbutils.version} - - org.yaml - snakeyaml - ${org.yaml.snakeyaml.version} - @@ -301,7 +285,6 @@ - From 01dcc416e5857921dd21e8233fe2588c76a963c4 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 9 Dec 2023 15:37:55 +0800 Subject: [PATCH 019/129] fix RestParam bug --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-id-generator/pom.xml | 2 +- springboot-starter-security-jwt/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/rest/param/RestParam.java | 16 ---------------- 6 files changed, 5 insertions(+), 21 deletions(-) diff --git a/pom.xml b/pom.xml index cecd1c03..b6772394 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.4 + 2.7.5 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index dcccfc34..973e347b 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.4 + 2.7.5 4.0.0 diff --git a/springboot-starter-id-generator/pom.xml b/springboot-starter-id-generator/pom.xml index f228fb24..2df5ea76 100644 --- a/springboot-starter-id-generator/pom.xml +++ b/springboot-starter-id-generator/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.4 + 2.7.5 4.0.0 diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index e1d89429..97b1705d 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.4 + 2.7.5 springboot-starter-security-jwt diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index ff00567b..85bb6c14 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.4 + 2.7.5 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java index 7ad699a5..465d0b0f 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java @@ -1,6 +1,5 @@ package com.codingapi.springboot.framework.rest.param; -import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import lombok.SneakyThrows; import org.springframework.util.LinkedMultiValueMap; @@ -35,21 +34,6 @@ private static void fetch(JSONObject object, RestParam builder) { Object value = object.getObject(key, Object.class); if (value != null) { builder.add(key, value); - - if (value instanceof JSONObject) { - JSONObject jsonObject = (JSONObject) value; - fetch(jsonObject, builder); - } - - if (value instanceof JSONArray) { - JSONArray jsonArray = (JSONArray) value; - for (Object o : jsonArray) { - if (o instanceof JSONObject) { - JSONObject jsonObject = (JSONObject) o; - fetch(jsonObject, builder); - } - } - } } } } From c76ec004ecde730c3dd9ecc5981c4389fbc9991f Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Tue, 2 Jan 2024 14:37:59 +0800 Subject: [PATCH 020/129] update 2.7.6 --- docs/wiki/springboot-starter-data-fast.md | 158 ++++++++++-------- docs/wiki/springboot-starter-id-generator.md | 34 ---- pom.xml | 32 +++- springboot-starter-data-fast/pom.xml | 28 +++- .../fast/DataFastConfiguration.java | 26 +-- .../fast/annotation/FastController.java | 11 -- .../fast/annotation/FastMapping.java | 38 ----- .../fast/dynamic/DynamicConfiguration.java | 21 --- .../fast/dynamic/DynamicQueryContext.java | 23 --- .../dynamic/DynamicQueryContextRegister.java | 16 -- .../exception/FastMappingErrorException.java | 8 - .../springboot/fast/executor/JpaExecutor.java | 39 ----- .../springboot/fast/executor/JpaQuery.java | 114 ------------- .../fast/executor/MvcMethodInterceptor.java | 39 ----- .../springboot/fast/jdbc/JdbcQuery.java | 71 ++++++++ .../fast/jdbc/JdbcQueryConfiguration.java | 22 +++ .../fast/jdbc/JdbcQueryContext.java | 23 +++ .../fast/jdbc/JdbcQueryContextRegister.java | 16 ++ .../DynamicQuery.java => jpa/JPAQuery.java} | 8 +- .../fast/jpa/JPAQueryConfiguration.java | 21 +++ .../fast/jpa/JPAQueryContextRegister.java | 16 ++ .../springboot/fast/jpa/JpaQueryContext.java | 23 +++ .../repository}/DynamicRepository.java | 13 +- .../repository}/FastRepository.java | 9 +- .../repository}/QueryRequest.java | 9 +- .../fast/manager/EntityManagerContent.java | 3 +- .../manager/EntityManagerInitializer.java | 3 +- ...ntMapping.java => MvcMappingRegister.java} | 24 ++- .../DataFastBeanDefinitionRegistrar.java | 33 ---- .../fast/registrar/MvcMappingRegistrar.java | 94 ----------- .../springboot/fast/script/ScriptMapping.java | 56 +++++++ .../fast/script/ScriptMappingRegister.java | 46 +++++ .../springboot/fast/script/ScriptMethod.java | 18 ++ .../springboot/fast/script/ScriptRequest.java | 46 +++++ .../springboot/fast/script/ScriptRuntime.java | 31 ++++ .../codingapi/springboot/fast/sort/ISort.java | 8 - .../springboot/fast/sort/SortRepository.java | 24 --- .../main/resources/META-INF/spring.factories | 4 +- ...ot.autoconfigure.AutoConfiguration.imports | 4 +- .../fast/DataFastApplicationTest.java | 34 ---- .../springboot/fast/DemoRepositoryTest.java | 50 ++---- .../springboot/fast/entity/Demo.java | 10 +- .../springboot/fast/query/FastDemoQuery.java | 23 --- .../fast/repository/DemoRepository.java | 5 +- .../fast/script/ScriptRuntimeTest.java | 16 ++ springboot-starter-id-generator/pom.xml | 37 ---- .../generator/AutoConfiguration.java | 27 --- .../springboot/generator/IdGenerate.java | 17 -- .../generator/IdGeneratorContext.java | 33 ---- .../springboot/generator/dao/DbHelper.java | 76 --------- .../springboot/generator/dao/IdKeyDao.java | 94 ----------- .../springboot/generator/domain/IdKey.java | 33 ---- .../properties/GeneratorJdbcProperties.java | 29 ---- .../generator/service/IdGenerateService.java | 24 --- .../main/resources/META-INF/spring.factories | 2 - ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../generator/IdGenerateServiceTest.java | 21 --- .../generator/IdGeneratorApplication.java | 12 -- .../src/test/resources/application.properties | 1 - springboot-starter-security-jwt/pom.xml | 2 +- springboot-starter/pom.xml | 12 +- .../framework/dto/request/IdRequest.java | 33 ++++ .../framework/dto/request/PageRequest.java | 14 +- .../springboot/framework/em/IEnum.java | 6 + .../serializable/EnumSerializer.java | 16 ++ 65 files changed, 696 insertions(+), 1144 deletions(-) delete mode 100644 docs/wiki/springboot-starter-id-generator.md delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/annotation/FastController.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/annotation/FastMapping.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicConfiguration.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContext.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContextRegister.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/exception/FastMappingErrorException.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaExecutor.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaQuery.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/MvcMethodInterceptor.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryConfiguration.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryContext.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryContextRegister.java rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/{dynamic/DynamicQuery.java => jpa/JPAQuery.java} (95%) create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryConfiguration.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryContextRegister.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContext.java rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/{dynamic => jpa/repository}/DynamicRepository.java (61%) rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/{query => jpa/repository}/FastRepository.java (94%) rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/{query => jpa/repository}/QueryRequest.java (99%) rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/{MvcEndpointMapping.java => MvcMappingRegister.java} (65%) delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/registrar/DataFastBeanDefinitionRegistrar.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/registrar/MvcMappingRegistrar.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMapping.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMappingRegister.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMethod.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRequest.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRuntime.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/ISort.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java delete mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DataFastApplicationTest.java delete mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/query/FastDemoQuery.java create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/script/ScriptRuntimeTest.java delete mode 100644 springboot-starter-id-generator/pom.xml delete mode 100644 springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/AutoConfiguration.java delete mode 100644 springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/IdGenerate.java delete mode 100644 springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/IdGeneratorContext.java delete mode 100644 springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/DbHelper.java delete mode 100644 springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/IdKeyDao.java delete mode 100644 springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/domain/IdKey.java delete mode 100644 springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/properties/GeneratorJdbcProperties.java delete mode 100644 springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/service/IdGenerateService.java delete mode 100644 springboot-starter-id-generator/src/main/resources/META-INF/spring.factories delete mode 100644 springboot-starter-id-generator/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 springboot-starter-id-generator/src/test/java/com/codingapi/springboot/generator/IdGenerateServiceTest.java delete mode 100644 springboot-starter-id-generator/src/test/java/com/codingapi/springboot/generator/IdGeneratorApplication.java delete mode 100644 springboot-starter-id-generator/src/test/resources/application.properties create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/IdRequest.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/em/IEnum.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/serializable/EnumSerializer.java diff --git a/docs/wiki/springboot-starter-data-fast.md b/docs/wiki/springboot-starter-data-fast.md index cd631789..aa35baca 100644 --- a/docs/wiki/springboot-starter-data-fast.md +++ b/docs/wiki/springboot-starter-data-fast.md @@ -2,53 +2,8 @@ springboot-starter-data-fast 基于JPA的快速API能力服务 -## FastController 快速API能力服务 -```java -package com.codingapi.springboot.example.query; - -import com.codingapi.springboot.example.infrastructure.jpa.entity.DemoEntity; -import com.codingapi.springboot.example.infrastructure.jpa.pojo.PageSearch; -import com.codingapi.springboot.fast.annotation.FastController; -import com.codingapi.springboot.fast.annotation.FastMapping; -import com.codingapi.springboot.framework.dto.response.MultiResponse; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.RequestMethod; - -@FastController -public interface FastDemoApi { - - - @PreAuthorize(value = "hasRole('ROLE_ADMIN')") - @FastMapping( - method = RequestMethod.GET, - mapping = "/api/demo/findByName1", - value = "select d from DemoEntity d where name = :name", - countQuery = "select count(d) from DemoEntity d where name = :name") - MultiResponse findByName1(PageSearch query); - - - - @PreAuthorize(value = "hasRole('ROLE_USER')") - @FastMapping( - method = RequestMethod.GET, - mapping = "/api/demo/findByName2", - value = "select d from DemoEntity d where name = :name", - countQuery = "select count(d) from DemoEntity d where name = :name") - MultiResponse findByName2(PageSearch query); - -} - -``` -@FastController 用于标记当前接口为Fast接口 -@FastMapping 用于标记当前接口的映射关系 -mapping为接口映射路径,method为接口请求方法 -value为查询语句,countQuery为查询总数语句,query为查询参数,支持分页查询,排序查询,查询参数等等 -MultiResponse为返回结果 -@PreAuthorize(value = "hasRole('ROLE_USER')") 用于标记当前接口的权限,如果不需要权限可以不用添加 - ## FastRepository 的使用教程 - 继承FastRepository接口,实现自定义的接口,即可使用FastRepository的能力 ```java @@ -189,41 +144,98 @@ public interface DemoRepository extends FastRepository { } ``` -## SortRepository的使用教程 -```java +## ScriptMapping 教程 -public interface DemoRepository extends FastRepository, SortRepository { +通过动态添加mvc mapping实现查询功能. -} ``` +ScriptMapping scriptMapping = new ScriptMapping({mapinggUrl}, {mapinggMethod}, {mappingGrovvry}); +scriptMappingRegister.addMapping(scriptMapping); -SortRepository的能力展示 +``` +mapinggUrl 是mvc接口的地址 +mapinggMethod 是mvc接口的请求方式 +mappingGrovvry 是执行的查询脚本 -```java +脚本实例代码: +* 动态分页查询 +``` +// 获取name的请求参数 +var name = $request.getParameter("name",""); +var pageNumber = $request.getParameter("pageNumber",0); +var pageSize = $request.getParameter("pageSize",10); +// 创建分页对象 +var pageRequest = $request.pageRequest(pageNumber,pageSize); +// 动态组织sql +var sql = "select * from api_mapping where 1 =1 "; +var countSql = "select count(1) from api_mapping where 1 =1 "; +// 动态组织参数 +var params = []; +if(!"".equals(name)){ + sql += " and name = ? "; + countSql += " and name = ? "; + params.push(name); +} +sql += " limit ?,?"; +// 添加分页参数 +params.add(pageRequest.getOffset()); +params.add(pageRequest.getPageSize()); +// 执行分页查询 +return $jdbc.queryForPage(sql,countSql,pageRequest,params.toArray()); +``` +* 动态条件查询 +``` +// 获取name的请求参数 +var name = $request.getParameter("name",""); +// 动态组织sql +String sql = "select * from api_mapping where 1=1 "; +// 动态组织参数 +var params = []; +if(!"".equals(name)){ + sql += " and name = ? "; + params.add(name); +} +// 执行查询 +return $jdbc.queryForList(sql,params.toArray()); +``` - @Test - @Transactional - void pageSort() { - demoRepository.deleteAll(); - Demo demo1 = new Demo(); - demo1.setName("123"); - demoRepository.save(demo1); - - Demo demo2 = new Demo(); - demo2.setName("456"); - demoRepository.save(demo2); - - List ids = Arrays.asList(demo1.getId(), demo2.getId()); - System.out.println(ids); - demoRepository.pageSort(PageRequest.of(1, 10), ids); - - Demo newDemo1 = demoRepository.getReferenceById(demo1.getId()); - Demo newDemo2 = demoRepository.getReferenceById(demo2.getId()); - - assertEquals(newDemo2.getSort(), 1); - assertEquals(newDemo1.getSort(), 0); - } +脚本语法介绍: +* $request +``` +// 获取参数name的值,如果参数不存在,则返回默认值 +var name = $request.getParameter("name",""); +// 获取分页对象 +var pageRequest = $request.pageRequest(0,10); +// 获取分页对象的页码 +var pageNumber = pageRequest.getPageNumber(); +// 获取分页对象的每页记录数 +var pageSize = pageRequest.getPageSize(); +// 获取分页对象的偏移量 +var offset = pageRequest.getOffset(); +``` +* $jdbc +``` +// 查询jdbcSQL $jdbc.queryForList({sql},{params}) + +// 查询无条件的数据 +var res = $jdbc.queryForList("select * from api_mapping"); +// 查询有条件的数据 +var res = $jdbc.queryForList("select * from api_mapping where name = ?",name); +// 查询多条件的数据 +var res = $jdbc.queryForList("select * from api_mapping where name = ? and url = ?",name,url); + +// 分页查询 $jdbc.queryForPage({sql},{countSql},{pageRequest},{params}) +var res = $jdbc.queryForPage("select * from api_mapping where name = ? and url = ?", +"select count(1) from api_mapping where name = ? and url = ?",pageRequest,params.toArray()); +``` +* $jpa +``` +// 查询jpa $jpa.listQuery({clazz},{sql},{params}) +// 查询无条件的数据 +var res = $jpa.listQuery(com.example.entity.NodeEntity.class,"from NodeEntity"); +// 查询有条件的数据 +var res = $jpa.listQuery(com.example.entity.NodeEntity.class,"from NodeEntity where name = ?",name); ``` \ No newline at end of file diff --git a/docs/wiki/springboot-starter-id-generator.md b/docs/wiki/springboot-starter-id-generator.md deleted file mode 100644 index 27bb96a9..00000000 --- a/docs/wiki/springboot-starter-id-generator.md +++ /dev/null @@ -1,34 +0,0 @@ -springboot-starter-id-generator - -一个单服务下的id自增构造器,为了解决id由数据库生成的问题,如果是分布式服务,可以使用snowflake算法生成id,如果是单服务,可以使用这个构造器生成id - -```java - -import com.codingapi.springboot.generator.IdGenerate; -import lombok.Getter; - -/** - * @author lorne - * @since 1.0.0 - */ -public class Demo implements IdGenerate { - - @Getter - private Integer id; - - @Getter - private String name; - - public Demo(String name) { - this.id = generateIntId(); - this.name = name; - } - -} - -``` - -只需要实现IdGenerate接口即可,然后调用generateIntId()方法即可生成id。 - -IdGenerate接口提供了两个方法,generateIntId()和generateLongId(),分别用于生成int类型和long类型的id。 -也可以使用generateStringId()方法生成String类型的id。 \ No newline at end of file diff --git a/pom.xml b/pom.xml index b6772394..f41008e8 100644 --- a/pom.xml +++ b/pom.xml @@ -6,13 +6,13 @@ org.springframework.boot spring-boot-starter-parent - 2.7.17 + 2.7.18 com.codingapi.springboot springboot-parent - 2.7.5 + 2.7.6 https://github.com/codingapi/springboot-framewrok springboot-parent @@ -35,11 +35,13 @@ 0.12.3 2.15.0 1.8.1 + 1.11.0 0.10.2 0.9.16 1.70 1.2.0 2.2 + 4.0.15 @@ -156,6 +158,29 @@ ${commons-dbutils.version} + + org.apache.commons + commons-text + ${commons-text.version} + + + + org.apache.groovy + groovy + ${apache-groovy.version} + + + + org.apache.groovy + groovy-json + ${apache-groovy.version} + + + + org.apache.groovy + groovy-xml + ${apache-groovy.version} + @@ -219,7 +244,6 @@ springboot-starter springboot-starter-security-jwt springboot-starter-data-fast - springboot-starter-id-generator @@ -231,7 +255,6 @@ springboot-starter springboot-starter-security-jwt springboot-starter-data-fast - springboot-starter-id-generator @@ -281,7 +304,6 @@ springboot-starter springboot-starter-security-jwt springboot-starter-data-fast - springboot-starter-id-generator diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 973e347b..b6e0468e 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.5 + 2.7.6 4.0.0 @@ -28,6 +28,12 @@ springboot-starter + + jakarta.servlet + jakarta.servlet-api + provided + + org.springframework.boot spring-boot-starter-data-jpa @@ -39,6 +45,26 @@ test + + org.apache.commons + commons-text + + + + org.apache.groovy + groovy + + + + org.apache.groovy + groovy-json + + + + org.apache.groovy + groovy-xml + + \ No newline at end of file diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java index f977da31..2fb91bcd 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java @@ -1,10 +1,8 @@ package com.codingapi.springboot.fast; -import com.codingapi.springboot.fast.executor.JpaExecutor; import com.codingapi.springboot.fast.manager.EntityManagerInitializer; -import com.codingapi.springboot.fast.mapping.MvcEndpointMapping; -import com.codingapi.springboot.fast.registrar.MvcMappingRegistrar; -import org.springframework.aop.Advisor; +import com.codingapi.springboot.fast.mapping.MvcMappingRegister; +import com.codingapi.springboot.fast.script.ScriptMappingRegister; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; @@ -13,7 +11,6 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import javax.persistence.EntityManager; -import java.util.List; @Configuration @ConditionalOnClass(WebMvcConfigurer.class) @@ -22,28 +19,21 @@ public class DataFastConfiguration { @Bean @ConditionalOnMissingBean - public MvcEndpointMapping mvcEndpointMapping(RequestMappingHandlerMapping handlerMapping) { - return new MvcEndpointMapping(handlerMapping); + public MvcMappingRegister mvcMappingRegister(RequestMappingHandlerMapping handlerMapping) { + return new MvcMappingRegister(handlerMapping); } - @Bean(initMethod = "registerMvcMapping") - @ConditionalOnMissingBean - public MvcMappingRegistrar mappingRegistrar(MvcEndpointMapping mvcEndpointMapping, - JpaExecutor jpaExecutor, - List advisors) { - return new MvcMappingRegistrar(mvcEndpointMapping, jpaExecutor,advisors); - } @Bean @ConditionalOnMissingBean - public EntityManagerInitializer entityManagerInitializer(EntityManager entityManager){ + public EntityManagerInitializer entityManagerInitializer(EntityManager entityManager) { return new EntityManagerInitializer(entityManager); } + @Bean - @ConditionalOnMissingBean - public JpaExecutor jpaExecutor(EntityManager entityManager) { - return new JpaExecutor(entityManager); + public ScriptMappingRegister scriptMappingRegister(MvcMappingRegister mvcMappingRegister) { + return new ScriptMappingRegister(mvcMappingRegister); } } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/annotation/FastController.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/annotation/FastController.java deleted file mode 100644 index e566cf7b..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/annotation/FastController.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.codingapi.springboot.fast.annotation; - -import java.lang.annotation.*; - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface FastController { - - -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/annotation/FastMapping.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/annotation/FastMapping.java deleted file mode 100644 index 1b1d8bb2..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/annotation/FastMapping.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.codingapi.springboot.fast.annotation; - - -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -@ResponseBody -public @interface FastMapping { - - /** - * execute jpa hql - */ - String value() default ""; - - - /** - * execute jpa count hql - */ - String countQuery() default ""; - - /** - * mvc request method - */ - RequestMethod method() default RequestMethod.GET; - - /** - * mvc request url - */ - String mapping() default ""; - -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicConfiguration.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicConfiguration.java deleted file mode 100644 index 1fe09262..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicConfiguration.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.codingapi.springboot.fast.dynamic; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.persistence.EntityManager; - -@Configuration -public class DynamicConfiguration { - - @Bean - public DynamicQuery dynamicQuery(EntityManager entityManager){ - return new DynamicQuery(entityManager); - } - - @Bean - public DynamicQueryContextRegister dynamicQueryContextRegister(DynamicQuery dynamicQuery){ - return new DynamicQueryContextRegister(dynamicQuery); - } - -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContext.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContext.java deleted file mode 100644 index 7e1e9230..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContext.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.codingapi.springboot.fast.dynamic; - - -import lombok.Getter; - -public class DynamicQueryContext { - - @Getter - private static final DynamicQueryContext instance = new DynamicQueryContext(); - - private DynamicQueryContext() { - - } - - @Getter - private DynamicQuery dynamicQuery; - - void setDynamicQuery(DynamicQuery dynamicQuery) { - this.dynamicQuery = dynamicQuery; - } - - -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContextRegister.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContextRegister.java deleted file mode 100644 index 4ed1cb8d..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQueryContextRegister.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.codingapi.springboot.fast.dynamic; - -import lombok.AllArgsConstructor; -import org.springframework.beans.factory.InitializingBean; - -@AllArgsConstructor -public class DynamicQueryContextRegister implements InitializingBean { - - private DynamicQuery dynamicQuery; - - @Override - public void afterPropertiesSet() throws Exception { - DynamicQueryContext.getInstance().setDynamicQuery(dynamicQuery); - } - -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/exception/FastMappingErrorException.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/exception/FastMappingErrorException.java deleted file mode 100644 index ce41c99c..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/exception/FastMappingErrorException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.codingapi.springboot.fast.exception; - -public class FastMappingErrorException extends Exception { - - public FastMappingErrorException(String message) { - super(message); - } -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaExecutor.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaExecutor.java deleted file mode 100644 index a7795989..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaExecutor.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.codingapi.springboot.fast.executor; - -import com.codingapi.springboot.framework.dto.response.MultiResponse; -import com.codingapi.springboot.framework.dto.response.SingleResponse; -import lombok.AllArgsConstructor; -import org.springframework.data.domain.Page; - -import javax.persistence.EntityManager; -import java.util.Collection; -import java.util.List; - -@AllArgsConstructor -public class JpaExecutor { - - private final EntityManager entityManager; - - public Object execute(String hql, String countHql, Object[] args, Class returnType) { - //only execute query sql - JpaQuery query = new JpaQuery(hql, countHql, args, entityManager); - - if (returnType.equals(SingleResponse.class)) { - List list = (List) query.getResultList(); - return list == null && list.size() > 0 ? SingleResponse.of(list.get(0)) : SingleResponse.empty(); - } - - if (returnType.equals(MultiResponse.class)) { - Object returnData = query.getResultList(); - if (Page.class.isAssignableFrom(returnData.getClass())) { - return MultiResponse.of((Page) returnData); - } - - if (Collection.class.isAssignableFrom(returnData.getClass())) { - return MultiResponse.of((Collection) returnData); - } - } - - return query.getResultList(); - } -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaQuery.java deleted file mode 100644 index 0aa880f0..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/JpaQuery.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.codingapi.springboot.fast.executor; - -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; - -import javax.persistence.EntityManager; -import javax.persistence.Parameter; -import javax.persistence.Query; -import java.lang.reflect.Field; -import java.util.Set; - -@Slf4j -public class JpaQuery { - private final Object[] args; - private final Query query; - private final String hql; - private final String countHql; - - private final EntityManager entityManager; - - public JpaQuery(String hql, String countHql, Object[] args, EntityManager entityManager) { - this.hql = hql; - this.countHql = countHql; - this.args = args; - this.entityManager = entityManager; - this.query = entityManager.createQuery(hql); - this.initParameter(query); - } - - /** - * init query parameter - */ - @SneakyThrows - private void initParameter(Query query) { - if (args != null && args.length > 0) { - Set> parameters = query.getParameters(); - for (Parameter parameter : parameters) { - Integer position = parameter.getPosition(); - if (position != null) { - query.setParameter(position, args[position - 1]); - } - if (StringUtils.hasText(parameter.getName())) { - String name = parameter.getName(); - Object obj = args[0]; - Field field = ReflectionUtils.findField(obj.getClass(), name); - if (field != null) { - field.setAccessible(true); - query.setParameter(name, field.get(obj)); - } - } - } - } - } - - /** - * is Page Request - */ - private boolean isPageable() { - if (args != null && args.length > 0 && StringUtils.hasText(countHql)) { - Object lastObj = args[args.length - 1]; - return lastObj instanceof Pageable; - } - return false; - } - - /** - * get PageRequest - */ - private Pageable getPageable() { - if (isPageable()) { - Object lastObj = args[args.length - 1]; - return (Pageable) lastObj; - } - return null; - } - - /** - * execute get list result data - */ - public Object getResultList() { - if (isPageable()) { - Pageable pageable = getPageable(); - query.setFirstResult((int) pageable.getOffset()); - query.setMaxResults(pageable.getPageSize()); - long total = getCount(); - return new PageImpl<>(query.getResultList(), pageable, total); - } - return query.getResultList(); - } - - - /** - * get sql execute data count - */ - private long getCount() { - Query countQuery = entityManager.createQuery(countHql); - initParameter(countQuery); - return (Long) countQuery.getSingleResult(); - } - - - /** - * get single result data - */ - public Object getSingleResult() { - return query.getSingleResult(); - } - - -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/MvcMethodInterceptor.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/MvcMethodInterceptor.java deleted file mode 100644 index fba74734..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/executor/MvcMethodInterceptor.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.codingapi.springboot.fast.executor; - -import com.codingapi.springboot.fast.annotation.FastMapping; -import lombok.AllArgsConstructor; -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - -import java.lang.reflect.Method; - -@AllArgsConstructor -public class MvcMethodInterceptor implements MethodInterceptor { - - private final JpaExecutor jpaExecutor; - - @Override - public Object invoke(MethodInvocation invocation) - throws Throwable { - Method method = invocation.getMethod(); - Object[] args = invocation.getArguments(); - - if (method.equals(Object.class.getMethod("equals", Object.class))) { - return false; - } - - if (method.equals(Object.class.getMethod("hashCode"))) { - return hashCode(); - } - - FastMapping fastMapping = method.getAnnotation(FastMapping.class); - if (fastMapping != null) { - Class returnType = method.getReturnType(); - return jpaExecutor.execute(fastMapping.value(), fastMapping.countQuery(), args, returnType); - } - // mvc mapping proxy can't execute return null. - return null; - } - - -} \ No newline at end of file diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java new file mode 100644 index 00000000..423ba1ea --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java @@ -0,0 +1,71 @@ +package com.codingapi.springboot.fast.jdbc; + +import org.apache.commons.text.CaseUtils; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.jdbc.core.BeanPropertyRowMapper; +import org.springframework.jdbc.core.RowMapper; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class JdbcQuery { + + private final org.springframework.jdbc.core.JdbcTemplate jdbcTemplate; + + public JdbcQuery(org.springframework.jdbc.core.JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + private static class CamelCaseRowMapper implements RowMapper> { + + @Override + public Map mapRow(ResultSet rs, int rowNum) throws SQLException { + ResultSetMetaData metaData = rs.getMetaData(); + int columnCount = metaData.getColumnCount(); + Map map = new HashMap<>(columnCount); + for (int i = 1; i <= columnCount; i++) { + String columnName = metaData.getColumnLabel(i); + map.put(CaseUtils.toCamelCase(columnName, false), rs.getObject(i)); + } + return map; + } + } + + public List> queryForList(String sql, Object... params) { + return jdbcTemplate.query(sql, params, new CamelCaseRowMapper()); + } + + public List queryForList(String sql, Class clazz, Object... params) { + return jdbcTemplate.query(sql, params, new BeanPropertyRowMapper<>(clazz)); + } + + public Page queryForPage(String sql, String countSql, Class clazz, PageRequest pageRequest, Object... params) { + List list = jdbcTemplate.query(sql, params, new BeanPropertyRowMapper<>(clazz)); + long count = this.countQuery(countSql, params); + return new PageImpl<>(list, pageRequest, count); + } + + public Page> queryForPage(String sql, String countSql, PageRequest pageRequest, Object... params) { + List> list = jdbcTemplate.query(sql, params, new CamelCaseRowMapper()); + + long count = this.countQuery(countSql, params); + return new PageImpl<>(list, pageRequest, count); + } + + + private long countQuery(String sql, Object... params) { + int paramsLength = params.length; + int countSqlParamsLength = sql.split("\\?").length - 1; + Object[] newParams = new Object[countSqlParamsLength]; + if (paramsLength > countSqlParamsLength) { + System.arraycopy(params, 0, newParams, 0, countSqlParamsLength); + } + return jdbcTemplate.queryForObject(sql, newParams, Long.class); + } +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryConfiguration.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryConfiguration.java new file mode 100644 index 00000000..aa05bd84 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryConfiguration.java @@ -0,0 +1,22 @@ +package com.codingapi.springboot.fast.jdbc; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; + + +@Configuration +public class JdbcQueryConfiguration { + + @Bean + public JdbcQuery jdbcQuery(JdbcTemplate jdbcTemplate) { + return new JdbcQuery(jdbcTemplate); + } + + @Bean + public JdbcQueryContextRegister jdbcQueryContextRegister(JdbcQuery jdbcQuery){ + return new JdbcQueryContextRegister(jdbcQuery); + } + + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryContext.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryContext.java new file mode 100644 index 00000000..7aaa455e --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryContext.java @@ -0,0 +1,23 @@ +package com.codingapi.springboot.fast.jdbc; + + +import lombok.Getter; + +public class JdbcQueryContext { + + @Getter + private static final JdbcQueryContext instance = new JdbcQueryContext(); + + private JdbcQueryContext() { + + } + + @Getter + private JdbcQuery jdbcQuery; + + void setJdbcQuery(JdbcQuery jdbcQuery) { + this.jdbcQuery = jdbcQuery; + } + + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryContextRegister.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryContextRegister.java new file mode 100644 index 00000000..47ab903d --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQueryContextRegister.java @@ -0,0 +1,16 @@ +package com.codingapi.springboot.fast.jdbc; + +import lombok.AllArgsConstructor; +import org.springframework.beans.factory.InitializingBean; + +@AllArgsConstructor +public class JdbcQueryContextRegister implements InitializingBean { + + private JdbcQuery jdbcQuery; + + @Override + public void afterPropertiesSet() throws Exception { + JdbcQueryContext.getInstance().setJdbcQuery(jdbcQuery); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java similarity index 95% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQuery.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java index 5727d337..00d64c2a 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicQuery.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java @@ -1,16 +1,16 @@ -package com.codingapi.springboot.fast.dynamic; +package com.codingapi.springboot.fast.jpa; +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; import lombok.AllArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; -import javax.persistence.EntityManager; -import javax.persistence.TypedQuery; import java.util.List; @AllArgsConstructor -public class DynamicQuery { +public class JPAQuery { private final EntityManager entityManager; diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryConfiguration.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryConfiguration.java new file mode 100644 index 00000000..598fe0c6 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryConfiguration.java @@ -0,0 +1,21 @@ +package com.codingapi.springboot.fast.jpa; + +import javax.persistence.EntityManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +public class JPAQueryConfiguration { + + @Bean + public JPAQuery dynamicQuery(EntityManager entityManager){ + return new JPAQuery(entityManager); + } + + @Bean + public JPAQueryContextRegister jpaQueryContextRegister(JPAQuery JPAQuery){ + return new JPAQueryContextRegister(JPAQuery); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryContextRegister.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryContextRegister.java new file mode 100644 index 00000000..b6fc7198 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryContextRegister.java @@ -0,0 +1,16 @@ +package com.codingapi.springboot.fast.jpa; + +import lombok.AllArgsConstructor; +import org.springframework.beans.factory.InitializingBean; + +@AllArgsConstructor +public class JPAQueryContextRegister implements InitializingBean { + + private JPAQuery JPAQuery; + + @Override + public void afterPropertiesSet() throws Exception { + JpaQueryContext.getInstance().setJPAQuery(JPAQuery); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContext.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContext.java new file mode 100644 index 00000000..e39b2d5c --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContext.java @@ -0,0 +1,23 @@ +package com.codingapi.springboot.fast.jpa; + + +import lombok.Getter; + +public class JpaQueryContext { + + @Getter + private static final JpaQueryContext instance = new JpaQueryContext(); + + private JpaQueryContext() { + + } + + @Getter + private JPAQuery JPAQuery; + + void setJPAQuery(JPAQuery JPAQuery) { + this.JPAQuery = JPAQuery; + } + + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java similarity index 61% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicRepository.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java index cd50e728..186f45a1 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java @@ -1,5 +1,6 @@ -package com.codingapi.springboot.fast.dynamic; +package com.codingapi.springboot.fast.jpa.repository; +import com.codingapi.springboot.fast.jpa.JpaQueryContext; import org.springframework.core.ResolvableType; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -18,23 +19,23 @@ default Class getEntityClass() { } default List dynamicListQuery(String sql, Object... params) { - return (List) DynamicQueryContext.getInstance().getDynamicQuery().listQuery(getEntityClass(), sql, params); + return (List) JpaQueryContext.getInstance().getJPAQuery().listQuery(getEntityClass(), sql, params); } default List dynamicListQuery(Class clazz, String sql, Object... params) { - return (List) DynamicQueryContext.getInstance().getDynamicQuery().listQuery(clazz, sql, params); + return (List) JpaQueryContext.getInstance().getJPAQuery().listQuery(clazz, sql, params); } default Page dynamicPageQuery(String sql, String countSql, PageRequest request, Object... params) { - return (Page) DynamicQueryContext.getInstance().getDynamicQuery().pageQuery(getEntityClass(), sql, countSql, request, params); + return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, countSql, request, params); } default Page dynamicPageQuery(String sql, PageRequest request, Object... params) { - return (Page) DynamicQueryContext.getInstance().getDynamicQuery().pageQuery(getEntityClass(), sql, "select count(1) " + sql, request, params); + return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, "select count(1) " + sql, request, params); } default Page dynamicPageQuery(Class clazz, String sql, String countSql, PageRequest request, Object... params) { - return (Page) DynamicQueryContext.getInstance().getDynamicQuery().pageQuery(clazz, sql, countSql, request, params); + return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(clazz, sql, countSql, request, params); } } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java similarity index 94% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java index c1a4374d..3e2f86bb 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java @@ -1,7 +1,8 @@ -package com.codingapi.springboot.fast.query; +package com.codingapi.springboot.fast.jpa.repository; -import com.codingapi.springboot.fast.dynamic.DynamicRepository; import com.codingapi.springboot.framework.dto.request.PageRequest; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Predicate; import org.springframework.core.ResolvableType; import org.springframework.data.domain.Page; import org.springframework.data.jpa.domain.Specification; @@ -9,8 +10,6 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.NoRepositoryBean; -import javax.persistence.criteria.Order; -import javax.persistence.criteria.Predicate; import java.util.List; @NoRepositoryBean @@ -48,4 +47,4 @@ default Page pageRequest(PageRequest request) { return findAll((org.springframework.data.domain.PageRequest) request); } -} \ No newline at end of file +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/QueryRequest.java similarity index 99% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/QueryRequest.java index 686ac1a8..4cf15162 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/QueryRequest.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/QueryRequest.java @@ -1,16 +1,15 @@ -package com.codingapi.springboot.fast.query; - +package com.codingapi.springboot.fast.jpa.repository; import com.codingapi.springboot.framework.dto.request.Filter; import com.codingapi.springboot.framework.dto.request.PageRequest; import com.codingapi.springboot.framework.dto.request.RequestFilter; -import org.springframework.beans.BeanUtils; -import org.springframework.data.domain.Example; - import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.Order; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; +import org.springframework.beans.BeanUtils; +import org.springframework.data.domain.Example; + import java.beans.PropertyDescriptor; import java.util.ArrayList; import java.util.Date; diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerContent.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerContent.java index 96ab6ba2..3fd6ab67 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerContent.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerContent.java @@ -1,8 +1,7 @@ package com.codingapi.springboot.fast.manager; -import lombok.Getter; - import javax.persistence.EntityManager; +import lombok.Getter; public class EntityManagerContent { diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerInitializer.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerInitializer.java index a262fc20..e77dd8b8 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerInitializer.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/manager/EntityManagerInitializer.java @@ -1,10 +1,9 @@ package com.codingapi.springboot.fast.manager; +import javax.persistence.EntityManager; import lombok.AllArgsConstructor; import org.springframework.beans.factory.InitializingBean; -import javax.persistence.EntityManager; - @AllArgsConstructor public class EntityManagerInitializer implements InitializingBean { diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/MvcEndpointMapping.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/MvcMappingRegister.java similarity index 65% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/MvcEndpointMapping.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/MvcMappingRegister.java index cf2eff3b..dfe3ed39 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/MvcEndpointMapping.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/MvcMappingRegister.java @@ -10,10 +10,11 @@ import java.lang.reflect.Method; @AllArgsConstructor -public class MvcEndpointMapping { +public class MvcMappingRegister { private final RequestMappingHandlerMapping handlerMapping; + /** * add mvc mapping * @@ -37,4 +38,25 @@ public void addMapping(String url, RequestMethod requestMethod, Object handler, handlerMapping.registerMapping(mappingInfo, handler, method); } + /** + * remove mvc mapping + * + * @param url mapping url + * @param requestMethod request method + */ + public void removeMapping(String url, RequestMethod requestMethod) { + RequestMappingInfo.BuilderConfiguration options = new RequestMappingInfo.BuilderConfiguration(); + options.setPatternParser(new PathPatternParser()); + + RequestMappingInfo mappingInfo = RequestMappingInfo + .paths(url) + .methods(requestMethod) + .produces(MediaType.APPLICATION_JSON_VALUE) + .options(options) + .build(); + + handlerMapping.unregisterMapping(mappingInfo); + } + + } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/registrar/DataFastBeanDefinitionRegistrar.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/registrar/DataFastBeanDefinitionRegistrar.java deleted file mode 100644 index 0a733ab7..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/registrar/DataFastBeanDefinitionRegistrar.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.codingapi.springboot.fast.registrar; - -import com.codingapi.springboot.fast.annotation.FastController; -import com.codingapi.springboot.framework.registrar.RegisterBeanScanner; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; -import org.springframework.core.type.AnnotationMetadata; - -import java.util.Set; - -@Slf4j -@Configuration -public class DataFastBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { - - - @SneakyThrows - @Override - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { - RegisterBeanScanner registerBeanScanner = new RegisterBeanScanner(importingClassMetadata, FastController.class); - Set> classSet = registerBeanScanner.findTypes(); - - //register bean - for (Class clazz : classSet) { - log.info("scanner @FastController class:{}", clazz); - MvcMappingRegistrar.classSet.add(clazz); - } - } - - -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/registrar/MvcMappingRegistrar.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/registrar/MvcMappingRegistrar.java deleted file mode 100644 index e6a154b8..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/registrar/MvcMappingRegistrar.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.codingapi.springboot.fast.registrar; - -import com.codingapi.springboot.fast.annotation.FastMapping; -import com.codingapi.springboot.fast.exception.FastMappingErrorException; -import com.codingapi.springboot.fast.executor.JpaExecutor; -import com.codingapi.springboot.fast.executor.MvcMethodInterceptor; -import com.codingapi.springboot.fast.mapping.MvcEndpointMapping; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.springframework.aop.Advisor; -import org.springframework.aop.framework.AdvisedSupport; -import org.springframework.aop.framework.AopProxy; -import org.springframework.aop.framework.AopProxyFactory; -import org.springframework.aop.framework.DefaultAopProxyFactory; -import org.springframework.data.domain.Pageable; -import org.springframework.util.StringUtils; - -import java.lang.reflect.Method; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -@Slf4j -public class MvcMappingRegistrar { - protected final static Set> classSet = new HashSet<>(); - private final MvcEndpointMapping mvcEndpointMapping; - - private final AopProxyFactory proxyFactory; - - private final List advisors; - - private final MvcMethodInterceptor interceptor; - - public MvcMappingRegistrar(MvcEndpointMapping mvcEndpointMapping, - JpaExecutor jpaExecutor, - List advisors) { - this.mvcEndpointMapping = mvcEndpointMapping; - this.advisors = advisors; - this.interceptor = new MvcMethodInterceptor(jpaExecutor); - this.proxyFactory = new DefaultAopProxyFactory(); - } - - @SneakyThrows - public void registerMvcMapping() { - for (Class clazz : classSet) { - Method[] methods = clazz.getDeclaredMethods(); - for (Method method : methods) { - FastMapping fastMapping = method.getAnnotation(FastMapping.class); - if (verify(fastMapping, method)) { - AdvisedSupport advisedSupport = createAdvisedSupport(clazz); - AopProxy proxy = proxyFactory.createAopProxy(advisedSupport); - mvcEndpointMapping.addMapping(fastMapping.mapping(), fastMapping.method(), - proxy.getProxy(), method); - } - } - } - } - - private AdvisedSupport createAdvisedSupport(Class clazz) { - AdvisedSupport advisedSupport = new AdvisedSupport(clazz); - advisedSupport.setTarget(interceptor); - advisedSupport.addAdvisors(advisors); - advisedSupport.addAdvice(interceptor); - return advisedSupport; - } - - private boolean verify(FastMapping fastMapping, Method method) throws FastMappingErrorException { - if (fastMapping == null) { - return false; - } - - if (!StringUtils.hasText(fastMapping.mapping())) { - throw new FastMappingErrorException(String.format("fast method %s missing mapping .", - method.getName())); - } - - if (!StringUtils.hasText(fastMapping.value())) { - throw new FastMappingErrorException(String.format("fast mapping %s missing value .", - fastMapping.mapping())); - } - - Class[] parameterTypes = method.getParameterTypes(); - for (Class parameter : parameterTypes) { - if (Pageable.class.isAssignableFrom(parameter)) { - if (!StringUtils.hasText(fastMapping.countQuery())) { - throw new FastMappingErrorException(String.format("fast mapping %s missing countQuery .", - fastMapping.mapping())); - } - } - } - return true; - } - -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMapping.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMapping.java new file mode 100644 index 00000000..3fc32f3b --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMapping.java @@ -0,0 +1,56 @@ +package com.codingapi.springboot.fast.script; + +import com.codingapi.springboot.framework.dto.response.MultiResponse; +import com.codingapi.springboot.framework.dto.response.Response; +import com.codingapi.springboot.framework.dto.response.SingleResponse; +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.lang.reflect.Method; +import java.util.List; + + +@Setter +@Getter +public class ScriptMapping { + + private String mapping; + private ScriptMethod scriptMethod; + private String script; + + + public ScriptMapping(String mapping, ScriptMethod scriptMethod, String script) { + this.mapping = mapping; + this.scriptMethod = scriptMethod; + this.script = script; + } + + @ResponseBody + Response execute() { + Object result = ScriptRuntime.running(script); + if (result instanceof List || result.getClass().isArray()) { + return SingleResponse.of(result); + } else { + if (result instanceof MultiResponse) { + return (MultiResponse) result; + } + if (result instanceof Page) { + return MultiResponse.of((Page) result); + } + return SingleResponse.of(result); + } + } + + + Method getExecuteMethod() { + try { + return this.getClass().getDeclaredMethod("execute"); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMappingRegister.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMappingRegister.java new file mode 100644 index 00000000..a94e9134 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMappingRegister.java @@ -0,0 +1,46 @@ +package com.codingapi.springboot.fast.script; + +import com.codingapi.springboot.fast.mapping.MvcMappingRegister; +import com.codingapi.springboot.framework.dto.response.Response; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class ScriptMappingRegister { + + private final MvcMappingRegister mappingRegister; + + /** + * test dynamic mapping + * + * @param scriptMapping dynamic mapping + **/ + public void addMapping(ScriptMapping scriptMapping) { + mappingRegister.addMapping(scriptMapping.getMapping(), scriptMapping.getScriptMethod().toRequestMethod(), + scriptMapping, scriptMapping.getExecuteMethod()); + } + + + /** + * test dynamic mapping + * + * @param scriptMapping dynamic mapping + * @return result + */ + public Response test(ScriptMapping scriptMapping) { + return scriptMapping.execute(); + } + + + /** + * remove mvc mapping + * + * @param url mapping url + * @param requestMethod request method + */ + public void removeMapping(String url, ScriptMethod scriptMethod){ + mappingRegister.removeMapping(url, scriptMethod.toRequestMethod()); + } + + + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMethod.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMethod.java new file mode 100644 index 00000000..8dfb44b6 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMethod.java @@ -0,0 +1,18 @@ +package com.codingapi.springboot.fast.script; + +import org.springframework.web.bind.annotation.RequestMethod; + +public enum ScriptMethod { + + GET, POST; + + + public RequestMethod toRequestMethod() { + if (this == GET) { + return RequestMethod.GET; + } else { + return RequestMethod.POST; + } + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRequest.java new file mode 100644 index 00000000..9b9f0e78 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRequest.java @@ -0,0 +1,46 @@ +package com.codingapi.springboot.fast.script; + +import javax.servlet.http.HttpServletRequest; +import com.codingapi.springboot.framework.dto.request.PageRequest; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class ScriptRequest { + + private final HttpServletRequest request; + + public String getParameter(String key, String defaultValue) { + String result = request.getParameter(key); + return result == null ? defaultValue : result; + } + + public int getParameter(String key, int defaultValue) { + String result = request.getParameter(key); + return result == null ? defaultValue : Integer.parseInt(result); + } + + public float getParameter(String key, float defaultValue) { + String result = request.getParameter(key); + return result == null ? defaultValue : Float.parseFloat(result); + } + + public double getParameter(String key, double defaultValue) { + String result = request.getParameter(key); + return result == null ? defaultValue : Double.parseDouble(result); + } + + public long getParameter(String key, long defaultValue) { + String result = request.getParameter(key); + return result == null ? defaultValue : Long.parseLong(result); + } + + public boolean getParameter(String key, boolean defaultValue) { + String result = request.getParameter(key); + return result == null ? defaultValue : Boolean.parseBoolean(result); + } + + public PageRequest pageRequest(int pageNumber, int pageSize) { + return PageRequest.of(pageNumber, pageSize); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRuntime.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRuntime.java new file mode 100644 index 00000000..2b5a63ba --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRuntime.java @@ -0,0 +1,31 @@ +package com.codingapi.springboot.fast.script; + +import com.codingapi.springboot.fast.jdbc.JdbcQuery; +import com.codingapi.springboot.fast.jdbc.JdbcQueryContext; +import com.codingapi.springboot.fast.jpa.JPAQuery; +import com.codingapi.springboot.fast.jpa.JpaQueryContext; +import groovy.lang.Binding; +import groovy.lang.GroovyShell; +import groovy.lang.Script; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + + +public class ScriptRuntime { + + static Object running(String script) { + Binding binding = new Binding(); + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); + ScriptRequest request = new ScriptRequest(attributes.getRequest()); + JdbcQuery jdbcQuery = JdbcQueryContext.getInstance().getJdbcQuery(); + JPAQuery jpaQuery = JpaQueryContext.getInstance().getJPAQuery(); + + binding.setVariable("$request", request); + binding.setVariable("$jpa", jpaQuery); + binding.setVariable("$jdbc", jdbcQuery); + + GroovyShell groovyShell = new GroovyShell(binding); + Script userScript = groovyShell.parse(script); + return userScript.run(); + } +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/ISort.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/ISort.java deleted file mode 100644 index b4a689d3..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/ISort.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.codingapi.springboot.fast.sort; - -public interface ISort { - - Integer getSort(); - - void setSort(Integer sort); -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java deleted file mode 100644 index 499ecd34..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/sort/SortRepository.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.codingapi.springboot.fast.sort; - -import com.codingapi.springboot.framework.dto.request.PageRequest; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.repository.NoRepositoryBean; - -import java.util.ArrayList; -import java.util.List; - -@NoRepositoryBean -public interface SortRepository extends JpaRepository { - - - default void pageSort(PageRequest request, List ids) { - List list = new ArrayList<>(); - for (int i = 0; i < ids.size(); i++) { - ISort entity = getReferenceById(ids.get(i)); - entity.setSort(i + (request.getPageNumber() * request.getPageSize())); - list.add((T) entity); - } - saveAll(list); - } - -} diff --git a/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories b/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories index 99726f46..f2d11256 100644 --- a/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories +++ b/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories @@ -1,4 +1,4 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.codingapi.springboot.fast.DataFastConfiguration,\ -com.codingapi.springboot.fast.registrar.DataFastBeanDefinitionRegistrar,\ -com.codingapi.springboot.fast.dynamic.DynamicConfiguration +com.codingapi.springboot.fast.jpa.JPAQueryConfiguration,\ +com.codingapi.springboot.fast.jdbc.JdbcQueryConfiguration \ No newline at end of file diff --git a/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index e8f74008..68b400af 100644 --- a/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,3 +1,3 @@ com.codingapi.springboot.fast.DataFastConfiguration -com.codingapi.springboot.fast.registrar.DataFastBeanDefinitionRegistrar -com.codingapi.springboot.fast.dynamic.DynamicConfiguration \ No newline at end of file +com.codingapi.springboot.fast.jpa.JPAQueryConfiguration +com.codingapi.springboot.fast.jdbc.JdbcQueryConfiguration \ No newline at end of file diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DataFastApplicationTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DataFastApplicationTest.java deleted file mode 100644 index 1870f2c4..00000000 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DataFastApplicationTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.codingapi.springboot.fast; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@AutoConfigureMockMvc -@SpringBootTest -public class DataFastApplicationTest { - - @Autowired - private MockMvc mockMvc; - - @Test - void findAll() throws Exception { - mockMvc.perform(get("/demo/findAll").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); - } - - @Test - void findById() throws Exception { - mockMvc.perform(get("/demo/getById").param("id", "1").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); - } - - @Test - void findPage() throws Exception { - mockMvc.perform(get("/demo/findPage").param("pageSize", "20").param("current", "1").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); - } -} diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index bb00452f..515c5550 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -5,19 +5,19 @@ import com.codingapi.springboot.framework.dto.request.Filter; import com.codingapi.springboot.framework.dto.request.PageRequest; import com.codingapi.springboot.framework.dto.request.Relation; +import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.Page; import org.springframework.data.domain.Sort; -import org.springframework.transaction.annotation.Transactional; -import java.util.Arrays; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +@Slf4j @SpringBootTest public class DemoRepositoryTest { @@ -70,14 +70,15 @@ void pageRequest() { PageRequest request = new PageRequest(); request.setCurrent(1); request.setPageSize(10); - request.addFilter("name", Relation.LIKE, "%2%"); + request.andFilter("name", Relation.LIKE, "%2%"); Page page = demoRepository.pageRequest(request); assertEquals(1, page.getTotalElements()); } + @Test - void customSearchOrFilters() { + void customInSearch() { demoRepository.deleteAll(); Demo demo1 = new Demo(); demo1.setName("123"); @@ -90,14 +91,17 @@ void customSearchOrFilters() { PageRequest request = new PageRequest(); request.setCurrent(1); request.setPageSize(10); - request.orFilters(Filter.as("name","123"),Filter.as("name","456")); + + request.andFilter("id", Relation.IN, 1, 2, 3); Page page = demoRepository.pageRequest(request); - assertEquals(2, page.getTotalElements()); + log.info("demo:{}", page.getContent()); +// assertEquals(2, page.getTotalElements()); } + @Test - void customSearchAddFilters() { + void customOrSearch() { demoRepository.deleteAll(); Demo demo1 = new Demo(); demo1.setName("123"); @@ -111,13 +115,14 @@ void customSearchAddFilters() { request.setCurrent(1); request.setPageSize(10); -// request.addFilters(Filter.as("id", Relation.IN, 1),Filter.as("id", Relation.IN, 2),Filter.as("id", Relation.IN, 3),Filter.as("id", Relation.IN, 4)); - request.andFilters(Filter.as("name", Relation.LIKE, "%2%"), Filter.and(Filter.as("id", Relation.IN, 1), Filter.as("id", Relation.IN, 2))); + + request.orFilters(Filter.as("id", Relation.IN, 1, 2, 3), Filter.as("name", "123")); + Page page = demoRepository.pageRequest(request); - assertEquals(0, page.getTotalElements()); + log.info("demo:{}", page.getContent()); +// assertEquals(2, page.getTotalElements()); } - @Test void dynamicListQuery() { demoRepository.deleteAll(); @@ -171,27 +176,4 @@ void sortQuery() { assertEquals(2, page.getTotalElements()); } - - @Test - @Transactional - void pageSort() { - demoRepository.deleteAll(); - Demo demo1 = new Demo(); - demo1.setName("123"); - demoRepository.save(demo1); - - Demo demo2 = new Demo(); - demo2.setName("456"); - demoRepository.save(demo2); - - List ids = Arrays.asList(demo1.getId(), demo2.getId()); - System.out.println(ids); - demoRepository.pageSort(PageRequest.of(1, 10), ids); - - Demo newDemo1 = demoRepository.getReferenceById(demo1.getId()); - Demo newDemo2 = demoRepository.getReferenceById(demo2.getId()); - - assertEquals(newDemo2.getSort(), 1); - assertEquals(newDemo1.getSort(), 0); - } } diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java index 4de36433..b4370905 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java @@ -1,18 +1,16 @@ package com.codingapi.springboot.fast.entity; -import com.codingapi.springboot.fast.sort.ISort; +import javax.persistence.*; import lombok.Getter; import lombok.Setter; - -import javax.persistence.*; - +import lombok.ToString; @Setter @Getter @Entity @Table(name = "t_demo") -public class Demo implements ISort { - +@ToString +public class Demo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/query/FastDemoQuery.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/query/FastDemoQuery.java deleted file mode 100644 index 50dd5939..00000000 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/query/FastDemoQuery.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.codingapi.springboot.fast.query; - -import com.codingapi.springboot.fast.annotation.FastController; -import com.codingapi.springboot.fast.annotation.FastMapping; -import com.codingapi.springboot.fast.entity.Demo; -import com.codingapi.springboot.framework.dto.request.PageRequest; -import com.codingapi.springboot.framework.dto.response.MultiResponse; -import com.codingapi.springboot.framework.dto.response.SingleResponse; -import org.springframework.web.bind.annotation.RequestParam; - -@FastController -public interface FastDemoQuery { - - @FastMapping(value = "select d from Demo d", mapping = "/demo/findAll") - MultiResponse findAll(); - - @FastMapping(value = "select d from Demo d where d.id = ?1", mapping = "/demo/getById") - SingleResponse getById(@RequestParam("id") int id); - - @FastMapping(value = "select d from Demo d", countQuery = "select count(d) from Demo d", mapping = "/demo/findPage") - MultiResponse findPage(PageRequest pageRequest); - -} diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/DemoRepository.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/DemoRepository.java index 9f5c76af..30a688b1 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/DemoRepository.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/DemoRepository.java @@ -1,9 +1,8 @@ package com.codingapi.springboot.fast.repository; import com.codingapi.springboot.fast.entity.Demo; -import com.codingapi.springboot.fast.query.FastRepository; -import com.codingapi.springboot.fast.sort.SortRepository; +import com.codingapi.springboot.fast.jpa.repository.FastRepository; -public interface DemoRepository extends FastRepository, SortRepository { +public interface DemoRepository extends FastRepository { } diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/script/ScriptRuntimeTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/script/ScriptRuntimeTest.java new file mode 100644 index 00000000..19e758db --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/script/ScriptRuntimeTest.java @@ -0,0 +1,16 @@ +package com.codingapi.springboot.fast.script; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +class ScriptRuntimeTest { + + @Test + void running() { + Object res = ScriptRuntime.running("return 1"); + assertEquals(1, res); + } +} \ No newline at end of file diff --git a/springboot-starter-id-generator/pom.xml b/springboot-starter-id-generator/pom.xml deleted file mode 100644 index 2df5ea76..00000000 --- a/springboot-starter-id-generator/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - springboot-parent - com.codingapi.springboot - 2.7.5 - - 4.0.0 - - springboot-starter-id-generator - - - 8 - - - - - - org.xerial - sqlite-jdbc - - - - commons-dbutils - commons-dbutils - - - - org.springframework - spring-jdbc - - - - - \ No newline at end of file diff --git a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/AutoConfiguration.java b/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/AutoConfiguration.java deleted file mode 100644 index e9a8b394..00000000 --- a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/AutoConfiguration.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.codingapi.springboot.generator; - -import com.codingapi.springboot.generator.dao.IdKeyDao; -import com.codingapi.springboot.generator.properties.GeneratorJdbcProperties; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class AutoConfiguration { - - @Bean - @ConfigurationProperties(prefix = "codingapi.id.jdbc.generator") - public GeneratorJdbcProperties generatorJdbcProperties() { - return new GeneratorJdbcProperties(); - } - - @Bean(initMethod = "init") - @ConditionalOnMissingBean - public IdKeyDao idKeyDao(GeneratorJdbcProperties generatorJdbcProperties) { - IdKeyDao keyDao = new IdKeyDao(generatorJdbcProperties.openDataSource()); - IdGeneratorContext.getInstance().init(keyDao); - return keyDao; - } - -} diff --git a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/IdGenerate.java b/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/IdGenerate.java deleted file mode 100644 index 972459a8..00000000 --- a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/IdGenerate.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.codingapi.springboot.generator; - -public interface IdGenerate { - - default long generateLongId() { - return IdGeneratorContext.getInstance().generateId(getClass()); - } - - default int generateIntId() { - return (int) IdGeneratorContext.getInstance().generateId(getClass()); - } - - default String generateStringId() { - return String.valueOf(IdGeneratorContext.getInstance().generateId(getClass())); - } - -} diff --git a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/IdGeneratorContext.java b/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/IdGeneratorContext.java deleted file mode 100644 index c405ef30..00000000 --- a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/IdGeneratorContext.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.codingapi.springboot.generator; - -import com.codingapi.springboot.generator.dao.IdKeyDao; -import com.codingapi.springboot.generator.service.IdGenerateService; - -public class IdGeneratorContext { - - private static IdGeneratorContext instance; - private IdGenerateService idGenerateService; - - private IdGeneratorContext() { - } - - public static IdGeneratorContext getInstance() { - if (instance == null) { - synchronized (IdGeneratorContext.class) { - if (instance == null) { - instance = new IdGeneratorContext(); - } - } - } - return instance; - } - - long generateId(Class clazz) { - return idGenerateService.generateId(clazz); - } - - void init(IdKeyDao idKeyDao) { - idGenerateService = new IdGenerateService(idKeyDao); - } - -} diff --git a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/DbHelper.java b/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/DbHelper.java deleted file mode 100644 index 92b8191a..00000000 --- a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/DbHelper.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.codingapi.springboot.generator.dao; - -import org.apache.commons.dbutils.QueryRunner; - -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.SQLException; - -public class DbHelper { - - private final DataSource dataSource; - private final QueryRunner queryRunner; - - - public DbHelper(DataSource dataSource) { - this.dataSource = dataSource; - this.queryRunner = new QueryRunner(); - } - - public void execute(IExecute execute) throws SQLException { - Connection connection = dataSource.getConnection(); - execute.execute(connection, queryRunner); - connection.close(); - } - - public T updateAndQuery(IUpdateAndQuery execute) throws SQLException { - Connection connection = dataSource.getConnection(); - connection.setAutoCommit(false); - T res = execute.updateAndQuery(connection, queryRunner); - connection.commit(); - connection.close(); - return res; - } - - public int update(IUpdate execute) throws SQLException { - Connection connection = dataSource.getConnection(); - connection.setAutoCommit(false); - int res = execute.update(connection, queryRunner); - connection.commit(); - connection.close(); - return res; - } - - public T query(IQuery execute) throws SQLException { - Connection connection = dataSource.getConnection(); - T res = execute.query(connection, queryRunner); - connection.close(); - return res; - } - - - interface IExecute { - default void execute(Connection connection, QueryRunner queryRunner) throws SQLException { - } - } - - - interface IUpdateAndQuery { - default T updateAndQuery(Connection connection, QueryRunner queryRunner) throws SQLException { - return null; - } - } - - interface IUpdate { - default int update(Connection connection, QueryRunner queryRunner) throws SQLException { - return 0; - } - } - - interface IQuery { - default T query(Connection connection, QueryRunner queryRunner) throws SQLException { - return null; - } - } - -} diff --git a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/IdKeyDao.java b/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/IdKeyDao.java deleted file mode 100644 index 541a68a5..00000000 --- a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/dao/IdKeyDao.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.codingapi.springboot.generator.dao; - -import com.codingapi.springboot.generator.domain.IdKey; -import lombok.SneakyThrows; -import org.apache.commons.dbutils.QueryRunner; -import org.apache.commons.dbutils.ResultSetHandler; - -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -public class IdKeyDao { - - private final DbHelper> dbHelper; - - private final ResultSetHandler> handler; - - public IdKeyDao(DataSource dataSource) { - this.dbHelper = new DbHelper<>(dataSource); - this.handler = rs -> { - List list = new ArrayList<>(); - while (rs.next()) { - IdKey generator = new IdKey(); - generator.setKey(rs.getString("TAG")); - generator.setId(rs.getInt("ID")); - generator.setUpdateTime(rs.getLong("UPDATE_TIME")); - list.add(generator); - } - return list; - }; - } - - @SneakyThrows - public void save(IdKey generator) { - dbHelper.update(new DbHelper.IUpdate() { - @Override - public int update(Connection connection, QueryRunner queryRunner) throws SQLException { - List list = queryRunner.query(connection, "SELECT * FROM ID_GENERATOR WHERE TAG = ?", handler, generator.getKey()); - if (list != null && list.size() > 0) { - return 0; - } - - String sql = "INSERT INTO ID_GENERATOR (ID, UPDATE_TIME, TAG) VALUES (?, ?, ?)"; - return queryRunner.update(connection, sql, generator.getId(), generator.getUpdateTime(), generator.getKey()); - } - }); - } - - - @SneakyThrows - public IdKey getByKey(String key) { - return dbHelper.query(new DbHelper.IQuery>() { - @Override - public List query(Connection connection, QueryRunner queryRunner) throws SQLException { - return queryRunner.query(connection, "SELECT * FROM ID_GENERATOR WHERE TAG = ?", handler, key); - } - }).stream().findFirst().orElse(null); - } - - - @SneakyThrows - public IdKey updateMaxId(IdKey generator) { - return dbHelper.updateAndQuery(new DbHelper.IUpdateAndQuery>() { - @Override - public List updateAndQuery(Connection connection, QueryRunner queryRunner) throws SQLException { - queryRunner.update(connection, "UPDATE ID_GENERATOR SET ID = ID + 1 WHERE TAG = ?", generator.getKey()); - return queryRunner.query(connection, "SELECT * FROM ID_GENERATOR WHERE TAG = ?", handler, generator.getKey()); - } - }).stream().findFirst().orElse(null); - } - - - @SneakyThrows - public List findAll() throws SQLException { - return dbHelper.query(new DbHelper.IQuery>() { - @Override - public List query(Connection connection, QueryRunner queryRunner) throws SQLException { - return queryRunner.query(connection, "SELECT * FROM ID_GENERATOR", handler); - } - }); - } - - private void init() throws SQLException { - dbHelper.execute(new DbHelper.IExecute() { - @Override - public void execute(Connection connection, QueryRunner queryRunner) throws SQLException { - String sql = "CREATE TABLE IF NOT EXISTS ID_GENERATOR (TAG TEXT NOT NULL, ID INTEGER NOT NULL, UPDATE_TIME INTEGER NOT NULL, PRIMARY KEY (TAG))"; - queryRunner.update(connection, sql); - } - }); - } -} diff --git a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/domain/IdKey.java b/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/domain/IdKey.java deleted file mode 100644 index 0363383e..00000000 --- a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/domain/IdKey.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.codingapi.springboot.generator.domain; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Setter -@Getter -@NoArgsConstructor -public class IdKey { - - private String key; - private long id; - private long updateTime; - - public IdKey(String key, long id) { - this.key = key; - this.id = id; - this.updateTime = System.currentTimeMillis(); - } - - public IdKey(String key) { - this.key = key; - this.id = 1; - this.updateTime = System.currentTimeMillis(); - } - - public IdKey(String key, long id, long updateTime) { - this.key = key; - this.id = id; - this.updateTime = updateTime; - } -} diff --git a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/properties/GeneratorJdbcProperties.java b/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/properties/GeneratorJdbcProperties.java deleted file mode 100644 index 6d89224a..00000000 --- a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/properties/GeneratorJdbcProperties.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.codingapi.springboot.generator.properties; - -import lombok.Getter; -import lombok.Setter; -import org.springframework.jdbc.datasource.DriverManagerDataSource; - -import javax.sql.DataSource; - -@Setter -@Getter -public class GeneratorJdbcProperties { - - private String jdbcUrl = "jdbc:sqlite:db.db"; - - private String jdbcDriver = "org.sqlite.JDBC"; - - private String jdbcUsername = "sa"; - - private String jdbcPassword = "sa"; - - public DataSource openDataSource() { - final DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName(jdbcDriver); - dataSource.setUrl(jdbcUrl); - dataSource.setUsername(jdbcUsername); - dataSource.setPassword(jdbcPassword); - return dataSource; - } -} diff --git a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/service/IdGenerateService.java b/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/service/IdGenerateService.java deleted file mode 100644 index 9d7dc478..00000000 --- a/springboot-starter-id-generator/src/main/java/com/codingapi/springboot/generator/service/IdGenerateService.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.codingapi.springboot.generator.service; - -import com.codingapi.springboot.generator.dao.IdKeyDao; -import com.codingapi.springboot.generator.domain.IdKey; - -public class IdGenerateService { - - private final IdKeyDao keyDao; - - public IdGenerateService(IdKeyDao keyDao) { - this.keyDao = keyDao; - } - - public synchronized long generateId(Class clazz) { - IdKey idKey = keyDao.getByKey(clazz.getName()); - if (idKey == null) { - idKey = new IdKey(clazz.getName()); - keyDao.save(idKey); - } else { - keyDao.updateMaxId(idKey); - } - return idKey.getId(); - } -} diff --git a/springboot-starter-id-generator/src/main/resources/META-INF/spring.factories b/springboot-starter-id-generator/src/main/resources/META-INF/spring.factories deleted file mode 100644 index f30445ef..00000000 --- a/springboot-starter-id-generator/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.codingapi.springboot.generator.AutoConfiguration \ No newline at end of file diff --git a/springboot-starter-id-generator/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/springboot-starter-id-generator/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index c1aa4e07..00000000 --- a/springboot-starter-id-generator/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -com.codingapi.springboot.generator.AutoConfiguration \ No newline at end of file diff --git a/springboot-starter-id-generator/src/test/java/com/codingapi/springboot/generator/IdGenerateServiceTest.java b/springboot-starter-id-generator/src/test/java/com/codingapi/springboot/generator/IdGenerateServiceTest.java deleted file mode 100644 index a2176a7c..00000000 --- a/springboot-starter-id-generator/src/test/java/com/codingapi/springboot/generator/IdGenerateServiceTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.codingapi.springboot.generator; - -import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -@Slf4j -@SpringBootTest -class IdGenerateServiceTest { - - @Test - void generateId() { - for (int i = 0; i < 1000; i++) { - long id = IdGeneratorContext.getInstance().generateId(IdGenerateServiceTest.class); - log.info("id=>{}", id); - assertTrue(id > 0, "id generator error."); - } - } -} \ No newline at end of file diff --git a/springboot-starter-id-generator/src/test/java/com/codingapi/springboot/generator/IdGeneratorApplication.java b/springboot-starter-id-generator/src/test/java/com/codingapi/springboot/generator/IdGeneratorApplication.java deleted file mode 100644 index d7979615..00000000 --- a/springboot-starter-id-generator/src/test/java/com/codingapi/springboot/generator/IdGeneratorApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.codingapi.springboot.generator; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class IdGeneratorApplication { - - public static void main(String[] args) { - SpringApplication.run(IdGeneratorApplication.class, args); - } -} diff --git a/springboot-starter-id-generator/src/test/resources/application.properties b/springboot-starter-id-generator/src/test/resources/application.properties deleted file mode 100644 index 8a3b6d8a..00000000 --- a/springboot-starter-id-generator/src/test/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -codingapi.id.generator.jdbc-url=jdbc:h2:file:./test.db \ No newline at end of file diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index 97b1705d..fb8de0b4 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.5 + 2.7.6 springboot-starter-security-jwt diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 85bb6c14..a6283042 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.5 + 2.7.6 springboot-starter @@ -21,6 +21,16 @@ spring-data-commons + + jakarta.persistence + jakarta.persistence-api + + + + com.fasterxml.jackson.core + jackson-databind + + org.springframework spring-tx diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/IdRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/IdRequest.java new file mode 100644 index 00000000..b325423e --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/IdRequest.java @@ -0,0 +1,33 @@ +package com.codingapi.springboot.framework.dto.request; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class IdRequest { + + private String id; + + public String getStringId(){ + return id; + } + + public int getIntId(){ + return Integer.parseInt(id); + } + + public Long getLongId(){ + return Long.parseLong(id); + } + + public float getFloatId(){ + return Float.parseFloat(id); + } + + public double getDoubleId(){ + return Double.parseDouble(id); + } + + +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index 7c0eb2df..19a9282a 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -24,7 +24,7 @@ public class PageRequest extends org.springframework.data.domain.PageRequest { private org.springframework.data.domain.PageRequest pageRequest; public PageRequest(int current, int pageSize, Sort sort) { - super(current > 0 ? current-- : 0, pageSize, sort); + super(current, pageSize, sort); this.current = current; this.pageSize = pageSize; this.pageRequest = org.springframework.data.domain.PageRequest.of(current, pageSize, sort); @@ -99,17 +99,17 @@ public Sort getSort() { } @Override - public org.springframework.data.domain.PageRequest next() { + public PageRequest next() { return new PageRequest(current + 1, getPageSize(), getSort()); } @Override - public org.springframework.data.domain.PageRequest previous() { + public PageRequest previous() { return current == 0 ? this : new PageRequest(current - 1, getPageSize(), getSort()); } @Override - public org.springframework.data.domain.PageRequest first() { + public PageRequest first() { return new PageRequest(0, getPageSize(), getSort()); } @@ -162,7 +162,7 @@ public void addSort(Sort sort) { } } - public PageRequest addFilter(String key, Relation relation, Object... value) { + public PageRequest andFilter(String key, Relation relation, Object... value) { requestFilter.addFilter(key, relation, value); return this; } @@ -172,8 +172,8 @@ public PageRequest addFilter(String key, Object... value) { return this; } - public PageRequest andFilters(Filter... filters) { - requestFilter.andFilters(filters); + public PageRequest andFilter(Filter... value) { + requestFilter.andFilters(value); return this; } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/em/IEnum.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/em/IEnum.java new file mode 100644 index 00000000..d24151b1 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/em/IEnum.java @@ -0,0 +1,6 @@ +package com.codingapi.springboot.framework.em; + +public interface IEnum { + + int getCode(); +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/serializable/EnumSerializer.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/serializable/EnumSerializer.java new file mode 100644 index 00000000..338dcf20 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/serializable/EnumSerializer.java @@ -0,0 +1,16 @@ +package com.codingapi.springboot.framework.serializable; + +import com.codingapi.springboot.framework.em.IEnum; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +public class EnumSerializer extends JsonSerializer { + + @Override + public void serialize(IEnum iEnum, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeNumber(iEnum.getCode()); + } +} From 375e15aac88deedd6d15d0f82675cded0487da22 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Tue, 2 Jan 2024 14:45:29 +0800 Subject: [PATCH 021/129] update 2.7.6 --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index a3ddf406..16844a72 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ v.3.x 为springboot 3.x版本,使用jdk17版本 * springboot-starter | Springboot领域驱动框架 * springboot-starter-data-fast | 快速数据呈现框架 -* springboot-starter-id-generator | Id自增策略框架 * springboot-starter-security-jwt | security&jwt权限框架 ## SpringBoot DDD Architecture | SpringBoot DDD 框架图 @@ -42,13 +41,6 @@ v.3.x 为springboot 3.x版本,使用jdk17版本 ${last.version} - - - com.codingapi.springboot - springboot-starter-id-generator - ${last.version} - - com.codingapi.springboot From abb8b4c8de4f2ae9bab03df53d0154e598f5389a Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 2 Jan 2024 22:16:16 +0800 Subject: [PATCH 022/129] add 2.7.7.dev --- pom.xml | 22 ++++++++++++++++++---- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security-jwt/pom.xml | 2 +- springboot-starter/pom.xml | 4 ++-- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index f41008e8..59fc5002 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.6 + 2.7.7.dev https://github.com/codingapi/springboot-framewrok springboot-parent @@ -38,10 +38,11 @@ 1.11.0 0.10.2 0.9.16 - 1.70 + 1.77 1.2.0 2.2 4.0.15 + 1.3.12 @@ -74,10 +75,23 @@ + + ch.qos.logback + logback-classic + ${logback.version} + + + + ch.qos.logback + logback-core + ${logback.version} + + + org.bouncycastle - bcprov-jdk15on - ${bcprov-jdk15on.version} + bcprov-jdk18on + ${bcprov-jdk18on.version} diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index b6e0468e..553bbcd3 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.6 + 2.7.7.dev 4.0.0 diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index fb8de0b4..e349a1b9 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.6 + 2.7.7.dev springboot-starter-security-jwt diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index a6283042..00ace6d5 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.6 + 2.7.7.dev springboot-starter @@ -48,7 +48,7 @@ org.bouncycastle - bcprov-jdk15on + bcprov-jdk18on From f8b505b5cf8addf788a9200ccd3e1cd50c429f43 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 2 Jan 2024 22:30:37 +0800 Subject: [PATCH 023/129] fix h2database version --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index 59fc5002..679da4bd 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,7 @@ 2.2 4.0.15 1.3.12 + 2.2.224 @@ -75,6 +76,12 @@ + + com.h2database + h2 + ${h2.version} + + ch.qos.logback logback-classic From 3b6f11f8e4df1f3fbc01401bf2074e50ccf29e01 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 2 Jan 2024 22:37:39 +0800 Subject: [PATCH 024/129] fix docs --- docs/wiki/home.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/docs/wiki/home.md b/docs/wiki/home.md index df4ad067..4387f03d 100644 --- a/docs/wiki/home.md +++ b/docs/wiki/home.md @@ -16,14 +16,7 @@ maven install com.codingapi.springboot springboot-starter-data-fast ${last.version} - - - - - com.codingapi.springboot - springboot-starter-id-generator - ${last.version} - + @@ -36,6 +29,5 @@ maven install [springboot-starter](./springboot-starter) [springboot-starter-security-jwt](./springboot-starter-security-jwt) -[springboot-starter-id-generator](./springboot-starter-id-generator) [springboot-starter-data-fast](./springboot-starter-data-fast.md) \ No newline at end of file From 27669516a3e4c82ae0aadc97391bc44c8492500b Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 2 Jan 2024 22:46:22 +0800 Subject: [PATCH 025/129] fix test --- pom.xml | 14 -------------- .../src/test/resources/application.properties | 1 + .../src/test/resources/application.properties | 1 + 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index 679da4bd..fce76f60 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,6 @@ 1.2.0 2.2 4.0.15 - 1.3.12 2.2.224 @@ -82,19 +81,6 @@ ${h2.version} - - ch.qos.logback - logback-classic - ${logback.version} - - - - ch.qos.logback - logback-core - ${logback.version} - - - org.bouncycastle bcprov-jdk18on diff --git a/springboot-starter-data-fast/src/test/resources/application.properties b/springboot-starter-data-fast/src/test/resources/application.properties index c3ec648b..559cfc80 100644 --- a/springboot-starter-data-fast/src/test/resources/application.properties +++ b/springboot-starter-data-fast/src/test/resources/application.properties @@ -1,5 +1,6 @@ server.port=8088 spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:file:./test.db +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.show-sql=true \ No newline at end of file diff --git a/springboot-starter/src/test/resources/application.properties b/springboot-starter/src/test/resources/application.properties index c3ec648b..559cfc80 100644 --- a/springboot-starter/src/test/resources/application.properties +++ b/springboot-starter/src/test/resources/application.properties @@ -1,5 +1,6 @@ server.port=8088 spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:file:./test.db +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.show-sql=true \ No newline at end of file From 4e8c9d75ae351875cda69a1be9f64e128bea9096 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Wed, 3 Jan 2024 11:07:20 +0800 Subject: [PATCH 026/129] support FastRepository#pageRequest x.x.x search --- .../fast/jpa/repository/QueryRequest.java | 106 ++++++++++++++---- .../springboot/fast/UserRepositoryTest.java | 92 +++++++++++++++ .../springboot/fast/entity/Demo.java | 5 +- .../springboot/fast/entity/Profile.java | 21 ++++ .../springboot/fast/entity/User.java | 22 ++++ .../fast/repository/ProfileRepository.java | 9 ++ .../fast/repository/UserRepository.java | 9 ++ 7 files changed, 239 insertions(+), 25 deletions(-) create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/UserRepositoryTest.java create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Profile.java create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/User.java create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/ProfileRepository.java create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/UserRepository.java diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/QueryRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/QueryRequest.java index 4cf15162..5d179405 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/QueryRequest.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/QueryRequest.java @@ -3,17 +3,20 @@ import com.codingapi.springboot.framework.dto.request.Filter; import com.codingapi.springboot.framework.dto.request.PageRequest; import com.codingapi.springboot.framework.dto.request.RequestFilter; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.Order; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; import org.springframework.beans.BeanUtils; import org.springframework.data.domain.Example; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.OneToOne; +import javax.persistence.criteria.*; import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Set; public class QueryRequest { @@ -52,10 +55,22 @@ public Example getExample() { private List getClazzProperties() { + return getClazzProperties(clazz); + } + + private List getClazzProperties(Class clazz) { List properties = new ArrayList<>(); PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz); for (PropertyDescriptor descriptor : descriptors) { - properties.add(descriptor.getName()); + Class propertyType = descriptor.getPropertyType(); + String name = descriptor.getName(); + if (propertyType.getPackage() != null && !propertyType.getPackage().getName().startsWith("java")) { + List childProperties = getClazzProperties(propertyType); + for (String child : childProperties) { + properties.add(name + "." + child); + } + } + properties.add(name); } return properties; } @@ -73,91 +88,113 @@ public List getOrder(Root root, CriteriaBuilder criteriaBuilder) { return orderList; } + private Path getPathByKey(Root root, String key) { + String[] keys = key.split("\\."); + if (keys.length > 1) { + String lastKey = keys[keys.length-1]; + From current = root; + for (int i=0;i< keys.length-1;i++) { + String item = keys[i]; + Set joins = current.getJoins(); + for (Join join : joins) { + if (join.getModel().getBindableJavaType().getSimpleName().equalsIgnoreCase(item)) { + current = join; + } + } + } + return current.get(lastKey); + } else { + return root.get(key); + } + } + private Predicate toPredicate(Filter filter, CriteriaBuilder criteriaBuilder, Root root, List properties) { String key = filter.getKey(); if (filter.isAndFilters() || filter.isOrFilters() || properties.contains(key)) { + Path path = getPathByKey(root, key); + if (filter.isEqual()) { - return criteriaBuilder.equal(root.get(key), filter.getValue()[0]); + return criteriaBuilder.equal(path, filter.getValue()[0]); } if (filter.isLike()) { String matchValue = (String) filter.getValue()[0]; - return criteriaBuilder.like(root.get(key), "%" + matchValue + "%"); + return criteriaBuilder.like(path, "%" + matchValue + "%"); } if (filter.isBetween()) { Object value1 = filter.getValue()[0]; Object value2 = filter.getValue()[2]; if (value1 instanceof Integer && value2 instanceof Integer) { - return criteriaBuilder.between(root.get(key), (Integer) value1, (Integer) value2); + return criteriaBuilder.between(path, (Integer) value1, (Integer) value2); } if (value1 instanceof Long && value2 instanceof Long) { - return criteriaBuilder.between(root.get(key), (Long) value1, (Long) value2); + return criteriaBuilder.between(path, (Long) value1, (Long) value2); } if (value1 instanceof Date && value2 instanceof Date) { - return criteriaBuilder.between(root.get(key), (Date) value1, (Date) value2); + return criteriaBuilder.between(path, (Date) value1, (Date) value2); } } if (filter.isGreaterThan()) { Object value = filter.getValue()[0]; if (value instanceof Integer) { - return criteriaBuilder.greaterThan(root.get(key), (Integer) value); + return criteriaBuilder.greaterThan(path, (Integer) value); } if (value instanceof Long) { - return criteriaBuilder.greaterThan(root.get(key), (Long) value); + return criteriaBuilder.greaterThan(path, (Long) value); } if (value instanceof Date) { - return criteriaBuilder.greaterThan(root.get(key), (Date) value); + return criteriaBuilder.greaterThan(path, (Date) value); } } if (filter.isGreaterThanEqual()) { Object value = filter.getValue()[0]; if (value instanceof Integer) { - return criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Integer) value); + return criteriaBuilder.greaterThanOrEqualTo(path, (Integer) value); } if (value instanceof Long) { - return criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Long) value); + return criteriaBuilder.greaterThanOrEqualTo(path, (Long) value); } if (value instanceof Date) { - return criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Date) value); + return criteriaBuilder.greaterThanOrEqualTo(path, (Date) value); } } if (filter.isLessThan()) { Object value = filter.getValue()[0]; if (value instanceof Integer) { - return criteriaBuilder.lessThan(root.get(key), (Integer) value); + return criteriaBuilder.lessThan(path, (Integer) value); } if (value instanceof Long) { - return criteriaBuilder.lessThan(root.get(key), (Long) value); + return criteriaBuilder.lessThan(path, (Long) value); } if (value instanceof Date) { - return criteriaBuilder.lessThan(root.get(key), (Date) value); + return criteriaBuilder.lessThan(path, (Date) value); } } if (filter.isLessThanEqual()) { Object value = filter.getValue()[0]; if (value instanceof Integer) { - return criteriaBuilder.lessThanOrEqualTo(root.get(key), (Integer) value); + return criteriaBuilder.lessThanOrEqualTo(path, (Integer) value); } if (value instanceof Long) { - return criteriaBuilder.lessThanOrEqualTo(root.get(key), (Long) value); + return criteriaBuilder.lessThanOrEqualTo(path, (Long) value); } if (value instanceof Date) { - return criteriaBuilder.lessThanOrEqualTo(root.get(key), (Date) value); + return criteriaBuilder.lessThanOrEqualTo(path, (Date) value); } } if (filter.isIn()) { Object[] value = filter.getValue(); - CriteriaBuilder.In in = criteriaBuilder.in(root.get(key)); + CriteriaBuilder.In in = criteriaBuilder.in(path); for (Object item : value) { in.value(item); } @@ -192,10 +229,33 @@ private Predicate toPredicate(Filter filter, CriteriaBuilder criteriaBuilder } + private void fetchJoins(From root, Class clazz) { + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + if (field.getAnnotation(OneToOne.class) != null) { + Join join = root.join(field.getName(), JoinType.INNER); + this.fetchJoins(join, field.getType()); + } + if (field.getAnnotation(ManyToOne.class) != null) { + Join join = root.join(field.getName(), JoinType.INNER); + this.fetchJoins(join, field.getType()); + } + if (field.getAnnotation(OneToMany.class) != null) { + Join join = root.join(field.getName(), JoinType.INNER); + this.fetchJoins(join, field.getType()); + } + if (field.getAnnotation(ManyToMany.class) != null) { + Join join = root.join(field.getName(), JoinType.INNER); + this.fetchJoins(join, field.getType()); + } + } + } + public List getPredicate(Root root, CriteriaBuilder criteriaBuilder) { List predicates = new ArrayList<>(); List properties = getClazzProperties(); RequestFilter requestFilter = request.getRequestFilter(); + this.fetchJoins(root, clazz); for (Filter filter : requestFilter.getFilters()) { Predicate predicate = toPredicate(filter, criteriaBuilder, root, properties); if (predicate != null) { diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/UserRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/UserRepositoryTest.java new file mode 100644 index 00000000..1047c25b --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/UserRepositoryTest.java @@ -0,0 +1,92 @@ +package com.codingapi.springboot.fast; + +import com.codingapi.springboot.fast.entity.Demo; +import com.codingapi.springboot.fast.entity.Profile; +import com.codingapi.springboot.fast.entity.User; +import com.codingapi.springboot.fast.repository.DemoRepository; +import com.codingapi.springboot.fast.repository.ProfileRepository; +import com.codingapi.springboot.fast.repository.UserRepository; +import com.codingapi.springboot.framework.dto.request.PageRequest; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +@Slf4j +@SpringBootTest +public class UserRepositoryTest { + + @Autowired + private DemoRepository demoRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private ProfileRepository profileRepository; + + + @Test + void test1() { + + Demo demo = new Demo(); + demo.setName("123"); + demoRepository.save(demo); + + + Profile profile = new Profile(); + profile.setDemo(demo); + profile.setName("123"); + profileRepository.save(profile); + + + User user = new User(); + user.setName("li"); + user.setProfile(profile); + userRepository.save(user); + + assertTrue(demo.getId()>0); + assertTrue(user.getId()>0); + + PageRequest request = new PageRequest(); + request.addFilter("profile.demo.id",1); + Page page = userRepository.pageRequest(request); + System.out.println(page.getContent()); + + } + + + + @Test + void test2() { + + Demo demo = new Demo(); + demo.setName("123"); + demoRepository.save(demo); + + + Profile profile = new Profile(); + profile.setDemo(demo); + profile.setName("123"); + profileRepository.save(profile); + + + User user = new User(); + user.setName("li"); + user.setProfile(profile); + userRepository.save(user); + + assertTrue(demo.getId()>0); + assertTrue(user.getId()>0); + + PageRequest request = new PageRequest(); + request.addFilter("name","li"); + Page page = userRepository.pageRequest(request); + System.out.println(page.getContent()); + + } + +} diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java index b4370905..b0c922d7 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Demo.java @@ -1,15 +1,16 @@ package com.codingapi.springboot.fast.entity; -import javax.persistence.*; import lombok.Getter; import lombok.Setter; import lombok.ToString; +import javax.persistence.*; + @Setter @Getter @Entity -@Table(name = "t_demo") @ToString +@Table(name = "t_demo") public class Demo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Profile.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Profile.java new file mode 100644 index 00000000..3ef6bb4a --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Profile.java @@ -0,0 +1,21 @@ +package com.codingapi.springboot.fast.entity; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.*; + +@Entity +@Setter +@Getter +public class Profile { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + private String name; + + @OneToOne + private Demo demo; +} diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/User.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/User.java new file mode 100644 index 00000000..ab0b8815 --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/User.java @@ -0,0 +1,22 @@ +package com.codingapi.springboot.fast.entity; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.*; + +@Entity +@Setter +@Getter +@Table(name = "t_user") +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + private String name; + + @OneToOne + private Profile profile; +} diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/ProfileRepository.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/ProfileRepository.java new file mode 100644 index 00000000..51a377e8 --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/ProfileRepository.java @@ -0,0 +1,9 @@ +package com.codingapi.springboot.fast.repository; + +import com.codingapi.springboot.fast.entity.Profile; +import com.codingapi.springboot.fast.jpa.repository.FastRepository; + +public interface ProfileRepository extends FastRepository { + + +} diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/UserRepository.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/UserRepository.java new file mode 100644 index 00000000..e92382b0 --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/UserRepository.java @@ -0,0 +1,9 @@ +package com.codingapi.springboot.fast.repository; + +import com.codingapi.springboot.fast.entity.User; +import com.codingapi.springboot.fast.jpa.repository.FastRepository; + +public interface UserRepository extends FastRepository { + + +} From e44a9b19d1710a6d9f0ee5644f0501533b69bc1f Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Thu, 4 Jan 2024 23:54:35 +0800 Subject: [PATCH 027/129] fix FastRepository --- .../fast/jpa/repository/DynamicRequest.java | 138 +++++++++ .../fast/jpa/repository/ExampleRequest.java | 46 +++ .../fast/jpa/repository/FastRepository.java | 19 +- .../fast/jpa/repository/QueryRequest.java | 267 ------------------ .../springboot/fast/MenuRepositoryTest.java | 60 ++++ .../springboot/fast/entity/Menu.java | 22 ++ .../fast/repository/MenuRepository.java | 9 + .../framework/dto/request/PageRequest.java | 4 +- .../framework/dto/request/RequestFilter.java | 6 +- 9 files changed, 287 insertions(+), 284 deletions(-) create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRequest.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleRequest.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/QueryRequest.java create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/MenuRepositoryTest.java create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Menu.java create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/MenuRepository.java diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRequest.java new file mode 100644 index 00000000..59035275 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRequest.java @@ -0,0 +1,138 @@ +package com.codingapi.springboot.fast.jpa.repository; + +import com.codingapi.springboot.framework.dto.request.Filter; +import com.codingapi.springboot.framework.dto.request.PageRequest; +import com.codingapi.springboot.framework.dto.request.RequestFilter; +import org.springframework.data.domain.Sort; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class DynamicRequest { + + private final PageRequest request; + private final Class clazz; + + private final List params = new ArrayList<>(); + private int paramIndex = 1; + + public DynamicRequest(PageRequest request, Class clazz) { + this.request = request; + this.clazz = clazz; + } + + + public String getHql() { + StringBuilder hql = new StringBuilder("FROM " + clazz.getSimpleName() + " WHERE "); + RequestFilter requestFilter = request.getRequestFilter(); + if (requestFilter.hasFilter()) { + List filters = requestFilter.getFilters(); + for (int i = 0; i < filters.size(); i++) { + Filter filter = filters.get(i); + this.buildSQL(filter, hql); + if (i != filters.size() - 1) { + hql.append(" AND "); + } + } + } + + Sort sort = request.getSort(); + if (sort.isSorted()) { + hql.append(" ORDER BY "); + List orders = sort.toList(); + for (int i = 0; i < orders.size(); i++) { + Sort.Order order = orders.get(i); + hql.append(order.getProperty()).append(" ").append(order.getDirection().name()); + if (i != orders.size() - 1) { + hql.append(","); + } + } + } + + System.out.println(hql.toString()); + System.out.println(params); + return hql.toString(); + } + + + private void buildSQL(Filter filter, StringBuilder hql) { + if (filter.isOrFilters()) { + Filter[] orFilters = (Filter[]) filter.getValue(); + if (orFilters.length > 0) { + hql.append(" ( "); + for (int i = 0; i < orFilters.length; i++) { + Filter orFilter = orFilters[i]; + this.buildSQL(orFilter, hql); + if (i != orFilters.length - 1) { + hql.append(" OR "); + } + + } + hql.append(" )"); + } + } + + if (filter.isAndFilters()) { + Filter[] andFilters = (Filter[]) filter.getValue(); + if (andFilters.length > 0) { + hql.append(" ( "); + for (int i = 0; i < andFilters.length; i++) { + Filter andFilter = andFilters[i]; + this.buildSQL(andFilter, hql); + if (i != andFilters.length - 1) { + hql.append(" AND "); + } + } + hql.append(" )"); + } + } + + if (filter.isEqual()) { + hql.append(filter.getKey()).append(" = ?").append(paramIndex); + params.add(filter.getValue()[0]); + paramIndex++; + } + if (filter.isLike()) { + hql.append(filter.getKey()).append(" LIKE ?").append(paramIndex); + params.add("%" + filter.getValue()[0] + "%"); + paramIndex++; + } + if (filter.isIn()) { + hql.append(filter.getKey()).append(" IN (").append("?").append(paramIndex).append(")"); + params.add(Arrays.asList(filter.getValue())); + paramIndex++; + } + if (filter.isGreaterThan()) { + hql.append(filter.getKey()).append(" > ?").append(paramIndex); + params.add(filter.getValue()[0]); + paramIndex++; + } + if (filter.isLessThan()) { + hql.append(filter.getKey()).append(" < ?").append(paramIndex); + params.add(filter.getValue()[0]); + paramIndex++; + } + if (filter.isGreaterThanEqual()) { + hql.append(filter.getKey()).append(" >= ?").append(paramIndex); + params.add(filter.getValue()[0]); + paramIndex++; + } + if (filter.isLessThanEqual()) { + hql.append(filter.getKey()).append(" <= ?").append(paramIndex); + params.add(filter.getValue()[0]); + paramIndex++; + } + if (filter.isBetween()) { + hql.append(filter.getKey()).append(" BETWEEN ?").append(paramIndex).append(" AND ?").append(paramIndex + 1); + params.add(filter.getValue()[0]); + params.add(filter.getValue()[1]); + paramIndex += 2; + } + } + + + public Object[] getParams() { + return params.toArray(); + } +} \ No newline at end of file diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleRequest.java new file mode 100644 index 00000000..25ee2ed2 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleRequest.java @@ -0,0 +1,46 @@ +package com.codingapi.springboot.fast.jpa.repository; + +import com.codingapi.springboot.framework.dto.request.Filter; +import com.codingapi.springboot.framework.dto.request.PageRequest; +import com.codingapi.springboot.framework.dto.request.RequestFilter; +import org.springframework.beans.BeanUtils; +import org.springframework.data.domain.Example; + +import java.beans.PropertyDescriptor; + +public class ExampleRequest { + + private final PageRequest request; + private final Class clazz; + + public ExampleRequest(PageRequest request, Class clazz) { + this.request = request; + this.clazz = clazz; + } + + public Example getExample() { + RequestFilter requestFilter = request.getRequestFilter(); + if (!requestFilter.hasFilter()) { + return null; + } + Object entity = null; + try { + entity = clazz.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz); + for (PropertyDescriptor descriptor : descriptors) { + String name = descriptor.getName(); + Filter value = requestFilter.getFilter(name); + if (value != null) { + try { + descriptor.getWriteMethod().invoke(entity, value.getFilterValue(descriptor.getPropertyType())); + } catch (Exception e) { + } + } + } + return (Example) Example.of(entity); + } + +} \ No newline at end of file diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java index 3e2f86bb..4b55b787 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java @@ -1,25 +1,20 @@ package com.codingapi.springboot.fast.jpa.repository; import com.codingapi.springboot.framework.dto.request.PageRequest; -import javax.persistence.criteria.Order; -import javax.persistence.criteria.Predicate; import org.springframework.core.ResolvableType; import org.springframework.data.domain.Page; -import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.NoRepositoryBean; -import java.util.List; - @NoRepositoryBean public interface FastRepository extends JpaRepository, JpaSpecificationExecutor, DynamicRepository { default Page findAll(PageRequest request) { if (request.hasFilter()) { Class clazz = getDomainClass(); - QueryRequest queryRequest = new QueryRequest(request, clazz); - return findAll(queryRequest.getExample(), request); + ExampleRequest exampleRequest = new ExampleRequest(request, clazz); + return findAll(exampleRequest.getExample(), request); } return findAll((org.springframework.data.domain.PageRequest) request); } @@ -35,14 +30,8 @@ default Class getDomainClass() { default Page pageRequest(PageRequest request) { if (request.hasFilter()) { Class clazz = getDomainClass(); - Specification specification = (root, query, criteriaBuilder) -> { - QueryRequest queryRequest = new QueryRequest(request, clazz); - List predicates = queryRequest.getPredicate(root, criteriaBuilder); - List orderList = queryRequest.getOrder(root, criteriaBuilder); - return query.where(predicates.toArray(new Predicate[0])).orderBy(orderList).getRestriction(); - }; - - return findAll(specification, request); + DynamicRequest dynamicRequest = new DynamicRequest(request,clazz); + return dynamicPageQuery(dynamicRequest.getHql(), request, dynamicRequest.getParams()); } return findAll((org.springframework.data.domain.PageRequest) request); } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/QueryRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/QueryRequest.java deleted file mode 100644 index 5d179405..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/QueryRequest.java +++ /dev/null @@ -1,267 +0,0 @@ -package com.codingapi.springboot.fast.jpa.repository; - -import com.codingapi.springboot.framework.dto.request.Filter; -import com.codingapi.springboot.framework.dto.request.PageRequest; -import com.codingapi.springboot.framework.dto.request.RequestFilter; -import org.springframework.beans.BeanUtils; -import org.springframework.data.domain.Example; - -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; -import javax.persistence.criteria.*; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Set; - -public class QueryRequest { - - private final PageRequest request; - private final Class clazz; - - public QueryRequest(PageRequest request, Class clazz) { - this.request = request; - this.clazz = clazz; - } - - public Example getExample() { - RequestFilter requestFilter = request.getRequestFilter(); - if (!requestFilter.hasFilter()) { - return null; - } - Object entity = null; - try { - entity = clazz.getDeclaredConstructor().newInstance(); - } catch (Exception e) { - throw new RuntimeException(e); - } - PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz); - for (PropertyDescriptor descriptor : descriptors) { - String name = descriptor.getName(); - Filter value = requestFilter.getFilter(name); - if (value != null) { - try { - descriptor.getWriteMethod().invoke(entity, value.getFilterValue(descriptor.getPropertyType())); - } catch (Exception e) { - } - } - } - return (Example) Example.of(entity); - } - - - private List getClazzProperties() { - return getClazzProperties(clazz); - } - - private List getClazzProperties(Class clazz) { - List properties = new ArrayList<>(); - PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz); - for (PropertyDescriptor descriptor : descriptors) { - Class propertyType = descriptor.getPropertyType(); - String name = descriptor.getName(); - if (propertyType.getPackage() != null && !propertyType.getPackage().getName().startsWith("java")) { - List childProperties = getClazzProperties(propertyType); - for (String child : childProperties) { - properties.add(name + "." + child); - } - } - properties.add(name); - } - return properties; - } - - - public List getOrder(Root root, CriteriaBuilder criteriaBuilder) { - List orderList = new ArrayList<>(); - request.getSort().forEach(sort -> { - if (sort.getDirection().isAscending()) { - orderList.add(criteriaBuilder.asc(root.get(sort.getProperty()))); - } else { - orderList.add(criteriaBuilder.asc(root.get(sort.getProperty()))); - } - }); - return orderList; - } - - private Path getPathByKey(Root root, String key) { - String[] keys = key.split("\\."); - if (keys.length > 1) { - String lastKey = keys[keys.length-1]; - From current = root; - for (int i=0;i< keys.length-1;i++) { - String item = keys[i]; - Set joins = current.getJoins(); - for (Join join : joins) { - if (join.getModel().getBindableJavaType().getSimpleName().equalsIgnoreCase(item)) { - current = join; - } - } - } - return current.get(lastKey); - } else { - return root.get(key); - } - } - - - private Predicate toPredicate(Filter filter, CriteriaBuilder criteriaBuilder, Root root, List properties) { - String key = filter.getKey(); - if (filter.isAndFilters() || filter.isOrFilters() || properties.contains(key)) { - - Path path = getPathByKey(root, key); - - if (filter.isEqual()) { - return criteriaBuilder.equal(path, filter.getValue()[0]); - } - - if (filter.isLike()) { - String matchValue = (String) filter.getValue()[0]; - return criteriaBuilder.like(path, "%" + matchValue + "%"); - } - - if (filter.isBetween()) { - Object value1 = filter.getValue()[0]; - Object value2 = filter.getValue()[2]; - if (value1 instanceof Integer && value2 instanceof Integer) { - return criteriaBuilder.between(path, (Integer) value1, (Integer) value2); - } - - if (value1 instanceof Long && value2 instanceof Long) { - return criteriaBuilder.between(path, (Long) value1, (Long) value2); - } - - if (value1 instanceof Date && value2 instanceof Date) { - return criteriaBuilder.between(path, (Date) value1, (Date) value2); - } - } - - if (filter.isGreaterThan()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - return criteriaBuilder.greaterThan(path, (Integer) value); - } - if (value instanceof Long) { - return criteriaBuilder.greaterThan(path, (Long) value); - } - if (value instanceof Date) { - return criteriaBuilder.greaterThan(path, (Date) value); - } - } - - if (filter.isGreaterThanEqual()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - return criteriaBuilder.greaterThanOrEqualTo(path, (Integer) value); - } - if (value instanceof Long) { - return criteriaBuilder.greaterThanOrEqualTo(path, (Long) value); - } - if (value instanceof Date) { - return criteriaBuilder.greaterThanOrEqualTo(path, (Date) value); - } - } - - if (filter.isLessThan()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - return criteriaBuilder.lessThan(path, (Integer) value); - } - if (value instanceof Long) { - return criteriaBuilder.lessThan(path, (Long) value); - } - if (value instanceof Date) { - return criteriaBuilder.lessThan(path, (Date) value); - } - } - - if (filter.isLessThanEqual()) { - Object value = filter.getValue()[0]; - if (value instanceof Integer) { - return criteriaBuilder.lessThanOrEqualTo(path, (Integer) value); - } - if (value instanceof Long) { - return criteriaBuilder.lessThanOrEqualTo(path, (Long) value); - } - if (value instanceof Date) { - return criteriaBuilder.lessThanOrEqualTo(path, (Date) value); - } - } - - if (filter.isIn()) { - Object[] value = filter.getValue(); - CriteriaBuilder.In in = criteriaBuilder.in(path); - for (Object item : value) { - in.value(item); - } - return in; - } - - if (filter.isOrFilters()) { - Filter[] orFilters = (Filter[]) filter.getValue(); - List orPredicates = new ArrayList<>(); - for (Filter orFilter : orFilters) { - Predicate predicate = toPredicate(orFilter, criteriaBuilder, root, properties); - if (predicate != null) { - orPredicates.add(predicate); - } - } - return criteriaBuilder.or(orPredicates.toArray(new Predicate[0])); - } - - if (filter.isAndFilters()) { - Filter[] orFilters = (Filter[]) filter.getValue(); - List addPredicates = new ArrayList<>(); - for (Filter orFilter : orFilters) { - Predicate predicate = toPredicate(orFilter, criteriaBuilder, root, properties); - if (predicate != null) { - addPredicates.add(predicate); - } - } - return criteriaBuilder.and(addPredicates.toArray(new Predicate[0])); - } - } - return null; - } - - - private void fetchJoins(From root, Class clazz) { - Field[] fields = clazz.getDeclaredFields(); - for (Field field : fields) { - if (field.getAnnotation(OneToOne.class) != null) { - Join join = root.join(field.getName(), JoinType.INNER); - this.fetchJoins(join, field.getType()); - } - if (field.getAnnotation(ManyToOne.class) != null) { - Join join = root.join(field.getName(), JoinType.INNER); - this.fetchJoins(join, field.getType()); - } - if (field.getAnnotation(OneToMany.class) != null) { - Join join = root.join(field.getName(), JoinType.INNER); - this.fetchJoins(join, field.getType()); - } - if (field.getAnnotation(ManyToMany.class) != null) { - Join join = root.join(field.getName(), JoinType.INNER); - this.fetchJoins(join, field.getType()); - } - } - } - - public List getPredicate(Root root, CriteriaBuilder criteriaBuilder) { - List predicates = new ArrayList<>(); - List properties = getClazzProperties(); - RequestFilter requestFilter = request.getRequestFilter(); - this.fetchJoins(root, clazz); - for (Filter filter : requestFilter.getFilters()) { - Predicate predicate = toPredicate(filter, criteriaBuilder, root, properties); - if (predicate != null) { - predicates.add(predicate); - } - } - return predicates; - } -} \ No newline at end of file diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/MenuRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/MenuRepositoryTest.java new file mode 100644 index 00000000..00cfe07c --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/MenuRepositoryTest.java @@ -0,0 +1,60 @@ +package com.codingapi.springboot.fast; + +import com.codingapi.springboot.fast.entity.Menu; +import com.codingapi.springboot.fast.repository.MenuRepository; +import com.codingapi.springboot.framework.dto.request.PageRequest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; + +import java.util.Arrays; +import java.util.List; + +@SpringBootTest +public class MenuRepositoryTest { + + @Autowired + private MenuRepository menuRepository; + + @Test + void test() { + + Menu parent = new Menu(); + parent.setName("parent"); + parent = menuRepository.save(parent); + + + Menu menu = new Menu(); + menu.setName("test"); + menu.setParent(parent); + menuRepository.save(menu); + + + PageRequest request = PageRequest.of(0, 10); + request.addFilter("parent.id", 1); + Page page = menuRepository.pageRequest(request); + System.out.println(page.getTotalElements()); + System.out.println(page.getContent()); + } + + + @Test + void test1() { + + Menu parent = new Menu(); + parent.setName("parent"); + parent = menuRepository.save(parent); + + + Menu menu = new Menu(); + menu.setName("test"); + menu.setParent(parent); + menuRepository.save(menu); + + + List menuList = menuRepository.dynamicListQuery("from Menu m where m.id in (?1)", Arrays.asList(1, 2)); + System.out.println(menuList); + } +} + diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Menu.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Menu.java new file mode 100644 index 00000000..efe7424c --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/entity/Menu.java @@ -0,0 +1,22 @@ +package com.codingapi.springboot.fast.entity; + +import javax.persistence.*; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Setter +@Getter +@Entity +@ToString +public class Menu { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + private String name; + + @ManyToOne + private Menu parent; + +} diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/MenuRepository.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/MenuRepository.java new file mode 100644 index 00000000..ed271005 --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/repository/MenuRepository.java @@ -0,0 +1,9 @@ +package com.codingapi.springboot.fast.repository; + +import com.codingapi.springboot.fast.entity.Menu; +import com.codingapi.springboot.fast.jpa.repository.FastRepository; + +public interface MenuRepository extends FastRepository { + + +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index 19a9282a..cb650b2e 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -1,12 +1,12 @@ package com.codingapi.springboot.framework.dto.request; -import javax.servlet.http.HttpServletRequest; import lombok.Getter; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +import javax.servlet.http.HttpServletRequest; import java.util.Optional; public class PageRequest extends org.springframework.data.domain.PageRequest { @@ -44,6 +44,7 @@ public PageRequest() { public void setCurrent(int current) { this.current = current > 0 ? current - 1 : 0; + this.requestFilter.deleteFilter("current"); } public String getParameter(String key) { @@ -91,6 +92,7 @@ public int getPageSize() { public void setPageSize(int pageSize) { this.pageSize = pageSize; + this.requestFilter.deleteFilter("pageSize"); } @Override diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java index 5c4cf90e..7ea9232b 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java @@ -1,6 +1,5 @@ package com.codingapi.springboot.framework.dto.request; - import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; @@ -98,4 +97,9 @@ public boolean hasFilter() { public Filter getFilter(String name) { return this.filterMap.get(name); } + + public void deleteFilter(String current) { + this.filterMap.remove(current); + this.filterList.removeIf(item -> item.getKey().equals(current)); + } } From 3f1fadcbd8a0ac0f90c178792066eb9ad84602a8 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 5 Jan 2024 18:16:12 +0800 Subject: [PATCH 028/129] update 2.7.7 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../springboot/fast/jpa/repository/DynamicRequest.java | 2 -- springboot-starter-security-jwt/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index fce76f60..b083a83f 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.7.dev + 2.7.7 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 553bbcd3..f4cc7071 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.7.dev + 2.7.7 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRequest.java index 59035275..ef91f3c6 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRequest.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRequest.java @@ -50,8 +50,6 @@ public String getHql() { } } - System.out.println(hql.toString()); - System.out.println(params); return hql.toString(); } diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index e349a1b9..29babada 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.7.dev + 2.7.7 springboot-starter-security-jwt diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 00ace6d5..6422cce2 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.7.dev + 2.7.7 springboot-starter From 10eecc5d770cbc20acd13d1b2e9bf11eb5555b50 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 5 Jan 2024 18:27:24 +0800 Subject: [PATCH 029/129] update 2.7.8 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security-jwt/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index b083a83f..a38c1d6f 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.7 + 2.7.8 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index f4cc7071..8efb653a 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.7 + 2.7.8 4.0.0 diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index 29babada..7ba2c2bd 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.7 + 2.7.8 springboot-starter-security-jwt diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 6422cce2..62475341 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.7 + 2.7.8 springboot-starter From 5bf61432ac77e37645a8926cb174037fbee30883 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 6 Jan 2024 17:52:48 +0800 Subject: [PATCH 030/129] add SearchRequest --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- ...micRequest.java => DynamicSQLBuilder.java} | 13 +- ...xampleRequest.java => ExampleBuilder.java} | 7 +- .../fast/jpa/repository/FastRepository.java | 19 ++- .../fast/jpa/repository/SearchRequest.java | 154 ++++++++++++++++++ .../springboot/fast/DemoRepositoryTest.java | 14 +- springboot-starter-security-jwt/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/dto/request/Filter.java | 3 +- .../framework/dto/request/PageRequest.java | 55 +------ .../framework/dto/request/RequestFilter.java | 17 +- .../dto/request/PageRequestTest.java | 2 +- .../query/test/DemoRepositoryTest.java | 2 +- 14 files changed, 210 insertions(+), 84 deletions(-) rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/{DynamicRequest.java => DynamicSQLBuilder.java} (94%) rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/{ExampleRequest.java => ExampleBuilder.java} (92%) create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SearchRequest.java diff --git a/pom.xml b/pom.xml index a38c1d6f..58c1d5f5 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.8 + 2.7.9.dev https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 8efb653a..94d34948 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.8 + 2.7.9.dev 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java similarity index 94% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRequest.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java index ef91f3c6..06705ad8 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRequest.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java @@ -3,13 +3,18 @@ import com.codingapi.springboot.framework.dto.request.Filter; import com.codingapi.springboot.framework.dto.request.PageRequest; import com.codingapi.springboot.framework.dto.request.RequestFilter; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Sort; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -public class DynamicRequest { +/** + * 动态条件查询组装 + */ +@Slf4j +class DynamicSQLBuilder { private final PageRequest request; private final Class clazz; @@ -17,13 +22,13 @@ public class DynamicRequest { private final List params = new ArrayList<>(); private int paramIndex = 1; - public DynamicRequest(PageRequest request, Class clazz) { + public DynamicSQLBuilder(PageRequest request, Class clazz) { this.request = request; this.clazz = clazz; } - public String getHql() { + public String getHQL() { StringBuilder hql = new StringBuilder("FROM " + clazz.getSimpleName() + " WHERE "); RequestFilter requestFilter = request.getRequestFilter(); if (requestFilter.hasFilter()) { @@ -50,6 +55,8 @@ public String getHql() { } } + log.debug("hql:{}", hql); + log.debug("params:{}", params); return hql.toString(); } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleBuilder.java similarity index 92% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleRequest.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleBuilder.java index 25ee2ed2..6b72dec3 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleRequest.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleBuilder.java @@ -8,12 +8,15 @@ import java.beans.PropertyDescriptor; -public class ExampleRequest { +/** + * Example组装 + */ +class ExampleBuilder { private final PageRequest request; private final Class clazz; - public ExampleRequest(PageRequest request, Class clazz) { + public ExampleBuilder(PageRequest request, Class clazz) { this.request = request; this.clazz = clazz; } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java index 4b55b787..523d721b 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java @@ -7,14 +7,19 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.NoRepositoryBean; +/** + * 更强大的Repository对象 + * @param + * @param + */ @NoRepositoryBean public interface FastRepository extends JpaRepository, JpaSpecificationExecutor, DynamicRepository { default Page findAll(PageRequest request) { if (request.hasFilter()) { Class clazz = getDomainClass(); - ExampleRequest exampleRequest = new ExampleRequest(request, clazz); - return findAll(exampleRequest.getExample(), request); + ExampleBuilder exampleBuilder = new ExampleBuilder(request, clazz); + return findAll(exampleBuilder.getExample(), request); } return findAll((org.springframework.data.domain.PageRequest) request); } @@ -30,10 +35,16 @@ default Class getDomainClass() { default Page pageRequest(PageRequest request) { if (request.hasFilter()) { Class clazz = getDomainClass(); - DynamicRequest dynamicRequest = new DynamicRequest(request,clazz); - return dynamicPageQuery(dynamicRequest.getHql(), request, dynamicRequest.getParams()); + DynamicSQLBuilder dynamicSQLBuilder = new DynamicSQLBuilder(request, clazz); + return dynamicPageQuery(dynamicSQLBuilder.getHQL(), request, dynamicSQLBuilder.getParams()); } return findAll((org.springframework.data.domain.PageRequest) request); } + + default Page searchRequest(SearchRequest request) { + Class clazz = getDomainClass(); + return pageRequest(request.toPageRequest(clazz)); + } + } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SearchRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SearchRequest.java new file mode 100644 index 00000000..866b8870 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SearchRequest.java @@ -0,0 +1,154 @@ +package com.codingapi.springboot.fast.jpa.repository; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.codingapi.springboot.framework.dto.request.PageRequest; +import com.codingapi.springboot.framework.dto.request.Relation; +import javax.servlet.http.HttpServletRequest; +import org.springframework.data.domain.Sort; +import org.springframework.util.StringUtils; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Base64; +import java.util.Enumeration; +import java.util.List; +import java.util.stream.Collectors; + +/** + * HttpServletRequest 请求参数解析成 PageRequest对象 + */ +public class SearchRequest { + + private int current; + private int pageSize; + + private final HttpServletRequest request; + + private final List removeKeys = new ArrayList<>(); + + private final PageRequest pageRequest; + + public SearchRequest() { + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); + this.request = attributes.getRequest(); + this.pageRequest = new PageRequest(); + } + + public void setCurrent(int current) { + this.current = current - 1; + this.removeKeys.add("current"); + } + + public void setPageSize(int pageSize) { + this.pageSize = pageSize; + this.removeKeys.add("pageSize"); + } + + private String decode(String value) { + return new String(Base64.getDecoder().decode(value)); + } + + + static class ClassContent { + + private final Class clazz; + private final PageRequest pageRequest; + + public ClassContent(Class clazz, PageRequest pageRequest) { + this.clazz = clazz; + this.pageRequest = pageRequest; + } + + public void addFilter(String key, String value) { + Class keyClass = getKeyType(key); + Object v = JSON.parseObject(value, keyClass); + pageRequest.addFilter(key, Relation.EQUAL, v); + } + + public void addFilter(String key, List value) { + Class keyClass = getKeyType(key); + pageRequest.addFilter(key, Relation.IN, value.stream() + .map(v -> JSON.parseObject(v, keyClass)) + .toArray() + ); + } + + + private Class getKeyType(String key) { + String[] keys = key.split("\\."); + Class keyClass = clazz; + for (String k : keys) { + Field[] fields = keyClass.getDeclaredFields(); + for (Field field : fields) { + if (field.getName().equals(k)) { + keyClass = field.getType(); + break; + } + } + } + return keyClass; + } + + } + + PageRequest toPageRequest(Class clazz) { + pageRequest.setCurrent(current); + pageRequest.setPageSize(pageSize); + + ClassContent content = new ClassContent(clazz, pageRequest); + + String sort = request.getParameter("sort"); + if (StringUtils.hasLength(sort)) { + sort = decode(sort); + if (JSON.isValid(sort)) { + removeKeys.add("sort"); + JSONObject jsonObject = JSON.parseObject(sort); + for (String key : jsonObject.keySet()) { + String value = jsonObject.getString(key); + if ("ascend".equals(value)) { + pageRequest.addSort(Sort.by(key).ascending()); + } else { + pageRequest.addSort(Sort.by(key).descending()); + } + } + } + } + + + String filter = request.getParameter("filter"); + if (StringUtils.hasLength(filter)) { + filter = decode(filter); + if (JSON.isValid(filter)) { + removeKeys.add("filter"); + JSONObject jsonObject = JSON.parseObject(filter); + for (String key : jsonObject.keySet()) { + JSONArray value = jsonObject.getJSONArray(key); + if (value != null && !value.isEmpty()) { + List values = value.stream().map(Object::toString).collect(Collectors.toList()); + content.addFilter(key, values); + } + } + } + } + + Enumeration enumeration = request.getParameterNames(); + while (enumeration.hasMoreElements()){ + String key = enumeration.nextElement(); + if (!removeKeys.contains(key)) { + String value = request.getParameter(key); + if (StringUtils.hasLength(value)) { + content.addFilter(key, value); + } + } + } + + + return pageRequest; + } + + +} diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index 515c5550..9b2ec82a 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -47,7 +47,7 @@ void findAll() { demoRepository.save(demo2); PageRequest request = new PageRequest(); - request.setCurrent(1); + request.setCurrent(0); request.setPageSize(10); request.addFilter("name", "123"); @@ -68,9 +68,9 @@ void pageRequest() { demoRepository.save(demo2); PageRequest request = new PageRequest(); - request.setCurrent(1); + request.setCurrent(0); request.setPageSize(10); - request.andFilter("name", Relation.LIKE, "%2%"); + request.addFilter("name", Relation.LIKE, "%2%"); Page page = demoRepository.pageRequest(request); assertEquals(1, page.getTotalElements()); @@ -89,10 +89,10 @@ void customInSearch() { demoRepository.save(demo2); PageRequest request = new PageRequest(); - request.setCurrent(1); + request.setCurrent(0); request.setPageSize(10); - request.andFilter("id", Relation.IN, 1, 2, 3); + request.addFilter("id", Relation.IN, 1, 2, 3); Page page = demoRepository.pageRequest(request); log.info("demo:{}", page.getContent()); @@ -112,7 +112,7 @@ void customOrSearch() { demoRepository.save(demo2); PageRequest request = new PageRequest(); - request.setCurrent(1); + request.setCurrent(0); request.setPageSize(10); @@ -167,7 +167,7 @@ void sortQuery() { demoRepository.save(demo2); PageRequest request = new PageRequest(); - request.setCurrent(1); + request.setCurrent(0); request.setPageSize(10); request.addSort(Sort.by("id").descending()); diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index 7ba2c2bd..f77ce3af 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.8 + 2.7.9.dev springboot-starter-security-jwt diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 62475341..a1480fcc 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.8 + 2.7.9.dev springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java index 0acb1477..55c901b8 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java @@ -1,6 +1,5 @@ package com.codingapi.springboot.framework.dto.request; - import lombok.Getter; import lombok.Setter; @@ -26,7 +25,7 @@ public Filter(String key, Object... value) { } public Filter(String key, Filter... value) { - this(key, null, value); + this(key, null, value); } public static Filter as(String key, Relation relation, Object... value) { diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index cb650b2e..c81cec33 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -1,25 +1,25 @@ package com.codingapi.springboot.framework.dto.request; import lombok.Getter; +import lombok.Setter; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import javax.servlet.http.HttpServletRequest; import java.util.Optional; public class PageRequest extends org.springframework.data.domain.PageRequest { @Getter + @Setter private int current; + + @Setter + @Getter private int pageSize; @Getter private final RequestFilter requestFilter = new RequestFilter(); - @Getter - private HttpServletRequest servletRequest; private org.springframework.data.domain.PageRequest pageRequest; @@ -28,13 +28,6 @@ public PageRequest(int current, int pageSize, Sort sort) { this.current = current; this.pageSize = pageSize; this.pageRequest = org.springframework.data.domain.PageRequest.of(current, pageSize, sort); - - try { - ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); - this.servletRequest = attributes.getRequest(); - requestFilter.syncParameter(servletRequest); - } catch (Exception e) { - } } @@ -42,29 +35,6 @@ public PageRequest() { this(0, 20, Sort.unsorted()); } - public void setCurrent(int current) { - this.current = current > 0 ? current - 1 : 0; - this.requestFilter.deleteFilter("current"); - } - - public String getParameter(String key) { - return servletRequest.getParameter(key); - } - - public String getParameter(String key, String defaultValue) { - String result = servletRequest.getParameter(key); - return result == null ? defaultValue : result; - } - - public int getIntParameter(String key) { - return Integer.parseInt(servletRequest.getParameter(key)); - } - - public int getIntParameter(String key, int defaultValue) { - String result = servletRequest.getParameter(key); - return result == null ? defaultValue : Integer.parseInt(result); - } - public String getStringFilter(String key) { return requestFilter.getStringFilter(key); } @@ -85,15 +55,6 @@ public boolean hasFilter() { return requestFilter.hasFilter(); } - @Override - public int getPageSize() { - return pageSize; - } - - public void setPageSize(int pageSize) { - this.pageSize = pageSize; - this.requestFilter.deleteFilter("pageSize"); - } @Override public Sort getSort() { @@ -164,7 +125,7 @@ public void addSort(Sort sort) { } } - public PageRequest andFilter(String key, Relation relation, Object... value) { + public PageRequest addFilter(String key, Relation relation, Object... value) { requestFilter.addFilter(key, relation, value); return this; } @@ -174,8 +135,8 @@ public PageRequest addFilter(String key, Object... value) { return this; } - public PageRequest andFilter(Filter... value) { - requestFilter.andFilters(value); + public PageRequest andFilter(Filter... filters) { + requestFilter.andFilters(filters); return this; } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java index 7ea9232b..2e1ac3c6 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java @@ -2,8 +2,10 @@ import org.springframework.util.StringUtils; -import javax.servlet.http.HttpServletRequest; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class RequestFilter { @@ -40,17 +42,6 @@ public void pushFilter(Filter filter) { filterMap.put(filter.getKey(), filter); } - public void syncParameter(HttpServletRequest servletRequest) { - Enumeration enumeration = servletRequest.getParameterNames(); - while (enumeration.hasMoreElements()) { - String key = enumeration.nextElement(); - String value = servletRequest.getParameter(key); - if (StringUtils.hasText(value)) { - addFilter(key, value); - } - } - } - public String getStringFilter(String key) { Filter filter = filterMap.get(key); diff --git a/springboot-starter/src/test/java/com/codingapi/springboot/framework/dto/request/PageRequestTest.java b/springboot-starter/src/test/java/com/codingapi/springboot/framework/dto/request/PageRequestTest.java index e3584bfa..93028dd8 100644 --- a/springboot-starter/src/test/java/com/codingapi/springboot/framework/dto/request/PageRequestTest.java +++ b/springboot-starter/src/test/java/com/codingapi/springboot/framework/dto/request/PageRequestTest.java @@ -9,7 +9,7 @@ class PageRequestTest { @Test void test(){ PageRequest pageRequest = new PageRequest(); - pageRequest.setCurrent(2); + pageRequest.setCurrent(1); pageRequest.setPageSize(10); assertEquals(pageRequest.getCurrent(),1); diff --git a/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/test/DemoRepositoryTest.java b/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/test/DemoRepositoryTest.java index a35c577f..2b787c96 100644 --- a/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/test/DemoRepositoryTest.java +++ b/springboot-starter/src/test/java/com/codingapi/springboot/framework/query/test/DemoRepositoryTest.java @@ -67,7 +67,7 @@ void sort(){ demoRepository.save(demo2); PageRequest request = new PageRequest(); - request.setCurrent(1); + request.setCurrent(0); request.setPageSize(10); request.addSort(Sort.by("id").descending()); From aafe75586a7097589536ba06ca988d84d1c213c4 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 6 Jan 2024 18:14:41 +0800 Subject: [PATCH 031/129] add SearchRequest --- .../fast/jpa/repository/SearchRequest.java | 25 +++++++++++++++++++ .../framework/dto/request/PageRequest.java | 4 +++ .../framework/dto/request/RequestFilter.java | 6 ++--- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SearchRequest.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SearchRequest.java index 866b8870..40d002ba 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SearchRequest.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SearchRequest.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.codingapi.springboot.framework.dto.request.Filter; import com.codingapi.springboot.framework.dto.request.PageRequest; import com.codingapi.springboot.framework.dto.request.Relation; import javax.servlet.http.HttpServletRequest; @@ -53,6 +54,30 @@ private String decode(String value) { } + public void addSort(Sort sort) { + pageRequest.addSort(sort); + } + + public void removeFilter(String key) { + pageRequest.removeFilter(key); + } + + public PageRequest addFilter(String key, Relation relation, Object... value) { + return pageRequest.addFilter(key, relation, value); + } + + public PageRequest addFilter(String key, Object... value) { + return pageRequest.addFilter(key, value); + } + + public PageRequest andFilter(Filter... filters) { + return pageRequest.andFilter(filters); + } + + public PageRequest orFilters(Filter... filters) { + return pageRequest.orFilters(filters); + } + static class ClassContent { private final Class clazz; diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index c81cec33..ff5b3df5 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -125,6 +125,10 @@ public void addSort(Sort sort) { } } + public void removeFilter(String key) { + requestFilter.removeFilter(key); + } + public PageRequest addFilter(String key, Relation relation, Object... value) { requestFilter.addFilter(key, relation, value); return this; diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java index 2e1ac3c6..0773eac8 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java @@ -89,8 +89,8 @@ public Filter getFilter(String name) { return this.filterMap.get(name); } - public void deleteFilter(String current) { - this.filterMap.remove(current); - this.filterList.removeIf(item -> item.getKey().equals(current)); + public void removeFilter(String key) { + this.filterMap.remove(key); + this.filterList.removeIf(item -> item.getKey().equals(key)); } } From 216fc20dd804b4798bb5bda04abad24d503219f6 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 6 Jan 2024 18:21:00 +0800 Subject: [PATCH 032/129] add SearchRequest --- .../fast/jpa/repository/FastRepository.java | 1 + .../framework/dto/request}/SearchRequest.java | 13 +++++-------- 2 files changed, 6 insertions(+), 8 deletions(-) rename {springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository => springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request}/SearchRequest.java (92%) diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java index 523d721b..d3e2deb8 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java @@ -1,6 +1,7 @@ package com.codingapi.springboot.fast.jpa.repository; import com.codingapi.springboot.framework.dto.request.PageRequest; +import com.codingapi.springboot.framework.dto.request.SearchRequest; import org.springframework.core.ResolvableType; import org.springframework.data.domain.Page; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SearchRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java similarity index 92% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SearchRequest.java rename to springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java index 40d002ba..364a2dc8 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SearchRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java @@ -1,17 +1,14 @@ -package com.codingapi.springboot.fast.jpa.repository; +package com.codingapi.springboot.framework.dto.request; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.codingapi.springboot.framework.dto.request.Filter; -import com.codingapi.springboot.framework.dto.request.PageRequest; -import com.codingapi.springboot.framework.dto.request.Relation; -import javax.servlet.http.HttpServletRequest; import org.springframework.data.domain.Sort; import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Base64; @@ -20,7 +17,7 @@ import java.util.stream.Collectors; /** - * HttpServletRequest 请求参数解析成 PageRequest对象 + * HttpServletRequest 请求参数解析成 PageRequest对象 */ public class SearchRequest { @@ -120,7 +117,7 @@ private Class getKeyType(String key) { } - PageRequest toPageRequest(Class clazz) { + public PageRequest toPageRequest(Class clazz) { pageRequest.setCurrent(current); pageRequest.setPageSize(pageSize); @@ -161,7 +158,7 @@ PageRequest toPageRequest(Class clazz) { } Enumeration enumeration = request.getParameterNames(); - while (enumeration.hasMoreElements()){ + while (enumeration.hasMoreElements()) { String key = enumeration.nextElement(); if (!removeKeys.contains(key)) { String value = request.getParameter(key); From a39998b9f41603f6ca4b52f7f4e3d92af994ca92 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 6 Jan 2024 21:59:30 +0800 Subject: [PATCH 033/129] add SortRepository --- .../fast/jpa/repository/SortRepository.java | 35 +++++++++++++++++++ .../springboot/framework/domain/ISort.java | 8 +++++ .../framework/dto/request/SortRequest.java | 14 ++++++++ 3 files changed, 57 insertions(+) create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/domain/ISort.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SortRequest.java diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java new file mode 100644 index 00000000..9bbbeb9b --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java @@ -0,0 +1,35 @@ +package com.codingapi.springboot.fast.jpa.repository; + +import com.codingapi.springboot.framework.domain.ISort; +import com.codingapi.springboot.framework.dto.request.SortRequest; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.NoRepositoryBean; + +import java.util.ArrayList; +import java.util.List; + +@NoRepositoryBean +public interface SortRepository extends JpaRepository { + + + default void reSort(SortRequest request) { + if (request != null && !request.getIds().isEmpty()) { + List list = new ArrayList<>(); + int minSort = 0; + for (Object objectId : request.getIds()) { + ID id = (ID) objectId; + T t = getReferenceById(id); + if (t.getSort() != null && t.getSort() < minSort) { + minSort = t.getSort(); + } + list.add(t); + } + for (T t : list) { + t.setSort(minSort++); + } + saveAll(list); + } + } + + +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/domain/ISort.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/domain/ISort.java new file mode 100644 index 00000000..f9efc10a --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/domain/ISort.java @@ -0,0 +1,8 @@ +package com.codingapi.springboot.framework.domain; + +public interface ISort { + + void setSort(Integer sort); + + Integer getSort(); +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SortRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SortRequest.java new file mode 100644 index 00000000..25d5a9b9 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SortRequest.java @@ -0,0 +1,14 @@ +package com.codingapi.springboot.framework.dto.request; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Setter +@Getter +public class SortRequest { + + private List ids; + +} From b872ea0008b5a0e0ab7e734369631f531df34057 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 6 Jan 2024 22:06:35 +0800 Subject: [PATCH 034/129] add SortRepository --- .../springboot/fast/jpa/repository/SortRepository.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java index 9bbbeb9b..a4e64852 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java @@ -15,12 +15,14 @@ public interface SortRepository extends JpaRepository list = new ArrayList<>(); - int minSort = 0; + int minSort = Integer.MAX_VALUE; for (Object objectId : request.getIds()) { ID id = (ID) objectId; T t = getReferenceById(id); if (t.getSort() != null && t.getSort() < minSort) { minSort = t.getSort(); + }else{ + minSort = 0; } list.add(t); } From 9d5357575045964392f32fec99a457134f78ad73 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sat, 6 Jan 2024 22:11:36 +0800 Subject: [PATCH 035/129] add SortRepository --- .../springboot/fast/jpa/repository/SortRepository.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java index a4e64852..a47a0650 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java @@ -19,10 +19,12 @@ default void reSort(SortRequest request) { for (Object objectId : request.getIds()) { ID id = (ID) objectId; T t = getReferenceById(id); - if (t.getSort() != null && t.getSort() < minSort) { - minSort = t.getSort(); - }else{ + if (t.getSort() == null) { minSort = 0; + } else { + if (t.getSort() < minSort) { + minSort = t.getSort(); + } } list.add(t); } From 7b2d24715cf010f99ce86b2c8eb7e469cdb3495b Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Wed, 10 Jan 2024 10:50:18 +0800 Subject: [PATCH 036/129] add JPAQuery#pageQuery(Class clazz, String sql, PageRequest pageRequest, Object... params) --- .../main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java | 4 ++++ .../springboot/fast/jpa/repository/DynamicRepository.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java index 00d64c2a..6342af68 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java @@ -24,6 +24,10 @@ public List listQuery(Class clazz, String sql, Object... params) { return query.getResultList(); } + public Page pageQuery(Class clazz, String sql, PageRequest pageRequest, Object... params) { + return pageQuery(clazz,sql,"select count(1) " + sql,pageRequest,params); + } + public Page pageQuery(Class clazz, String sql, String countSql, PageRequest pageRequest, Object... params) { TypedQuery query = entityManager.createQuery(sql, clazz); if (params != null) { diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java index 186f45a1..992f8ab2 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java @@ -31,7 +31,7 @@ default Page dynamicPageQuery(String sql, String countSql, PageRequest reques } default Page dynamicPageQuery(String sql, PageRequest request, Object... params) { - return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, "select count(1) " + sql, request, params); + return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, request, params); } default Page dynamicPageQuery(Class clazz, String sql, String countSql, PageRequest request, Object... params) { From 94ffabc4f48a8f33731f12753e0ce4c0016feab8 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 11 Jan 2024 11:15:14 +0800 Subject: [PATCH 037/129] update 2.7.9 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security-jwt/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 58c1d5f5..68850240 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.9.dev + 2.7.9 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 94d34948..050b96ec 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.9.dev + 2.7.9 4.0.0 diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index f77ce3af..201790ef 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.9.dev + 2.7.9 springboot-starter-security-jwt diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index a1480fcc..415f2afa 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.9.dev + 2.7.9 springboot-starter From 592a579251e550a4a4d47707c9c1ac3d0792393a Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Mon, 29 Jan 2024 10:43:36 +0800 Subject: [PATCH 038/129] #38 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security-jwt/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/dto/request/SearchRequest.java | 11 +++++++++-- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 68850240..7c4fe039 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.9 + 2.7.10.dev https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 050b96ec..276a40f5 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.9 + 2.7.10.dev 4.0.0 diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index 201790ef..70daff27 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.9 + 2.7.10.dev springboot-starter-security-jwt diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 415f2afa..2904b224 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.9 + 2.7.10.dev springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java index 364a2dc8..07c53bdd 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java @@ -87,14 +87,21 @@ public ClassContent(Class clazz, PageRequest pageRequest) { public void addFilter(String key, String value) { Class keyClass = getKeyType(key); - Object v = JSON.parseObject(value, keyClass); + Object v = parseObject(value, keyClass); pageRequest.addFilter(key, Relation.EQUAL, v); } + private Object parseObject(String value, Class keyClass) { + if(value.getClass().equals(keyClass)) { + return value; + } + return JSON.parseObject(value, keyClass); + } + public void addFilter(String key, List value) { Class keyClass = getKeyType(key); pageRequest.addFilter(key, Relation.IN, value.stream() - .map(v -> JSON.parseObject(v, keyClass)) + .map(v -> parseObject(v, keyClass)) .toArray() ); } From e65a0dfd9fe9d25d1419a55f619a22ceae92d2e5 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Mon, 29 Jan 2024 10:44:02 +0800 Subject: [PATCH 039/129] fix #38 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security-jwt/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 7c4fe039..17d00ac7 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.10.dev + 2.7.10 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 276a40f5..dba73ff4 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.10.dev + 2.7.10 4.0.0 diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security-jwt/pom.xml index 70daff27..73c3f64f 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security-jwt/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.7.10.dev + 2.7.10 springboot-starter-security-jwt diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 2904b224..1cf03f54 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.10.dev + 2.7.10 springboot-starter From a0e87cbf2bdd78319ca642d0753d74e02731839a Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Sun, 31 Mar 2024 14:36:19 +0800 Subject: [PATCH 040/129] add security redis support --- README.md | 4 +- ...-jwt.md => springboot-starter-security.md} | 38 +++++++---- pom.xml | 12 ++-- springboot-starter-data-fast/pom.xml | 2 +- .../main/resources/META-INF/spring.factories | 4 -- ...ot.autoconfigure.AutoConfiguration.imports | 3 - .../pom.xml | 17 +++-- .../security/AutoConfiguration.java | 26 +++----- .../configurer/HttpSecurityConfigurer.java | 12 ++-- .../configurer/WebSecurityConfigurer.java | 6 +- .../controller/VersionController.java | 0 .../springboot/security/crypto/AESTools.java | 8 +-- .../crypto/SecurityCryptoConfiguration.java | 9 ++- .../security/dto/request/LoginRequest.java | 0 .../dto/request/LoginRequestContext.java | 0 .../security/dto/response/LoginResponse.java | 0 .../exception/TokenExpiredException.java | 0 .../filter/AuthenticationTokenFilter.java | 0 .../filter/MyAccessDeniedHandler.java | 0 .../filter/MyAuthenticationFilter.java | 22 +++---- .../security/filter/MyLoginFilter.java | 18 ++--- .../security/filter/MyLogoutHandler.java | 0 .../filter/MyLogoutSuccessHandler.java | 0 .../filter/MyUnAuthenticationEntryPoint.java | 0 .../security/filter/SecurityLoginHandler.java | 2 +- .../springboot/security/gateway}/Token.java | 8 +-- .../security/gateway}/TokenContext.java | 2 +- .../security/gateway/TokenGateway.java | 23 +++++++ .../jwt/JWTSecurityConfiguration.java | 35 ++++++++++ .../security/jwt/JWTTokenGatewayImpl.java | 25 +++++++ .../security/jwt/JwtTokenGateway.java | 21 +++--- .../security/jwt/SecurityJWTProperties.java | 35 ++++++++++ .../CodingApiSecurityProperties.java | 43 ++++-------- .../redis/RedisSecurityConfiguration.java | 35 ++++++++++ .../security/redis/RedisTokenGateway.java | 65 +++++++++++++++++++ .../security/redis/RedisTokenGatewayImpl.java | 26 ++++++++ .../redis/SecurityRedisProperties.java | 27 ++++++++ .../main/resources/META-INF/spring.factories | 6 ++ ...ot.autoconfigure.AutoConfiguration.imports | 5 ++ .../security/SecurityJwtApplication.java | 0 .../security/SecurityJwtApplicationTest.java | 0 .../security/controller/DemoController.java | 0 .../springboot/security/jwt/TestVO.java | 0 .../springboot/security/jwt/TokenTest.java | 16 +++-- .../src/test/resources/application.properties | 10 +-- springboot-starter/pom.xml | 2 +- 46 files changed, 420 insertions(+), 147 deletions(-) rename docs/wiki/{springboot-starter-security-jwt.md => springboot-starter-security.md} (79%) delete mode 100644 springboot-starter-security-jwt/src/main/resources/META-INF/spring.factories delete mode 100644 springboot-starter-security-jwt/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename {springboot-starter-security-jwt => springboot-starter-security}/pom.xml (73%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java (86%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java (72%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/configurer/WebSecurityConfigurer.java (71%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/controller/VersionController.java (100%) rename springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/crypto/MyAES.java => springboot-starter-security/src/main/java/com/codingapi/springboot/security/crypto/AESTools.java (84%) rename springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/crypto/MyCryptoConfiguration.java => springboot-starter-security/src/main/java/com/codingapi/springboot/security/crypto/SecurityCryptoConfiguration.java (69%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/dto/request/LoginRequest.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/dto/request/LoginRequestContext.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/dto/response/LoginResponse.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/exception/TokenExpiredException.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java (77%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java (87%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/filter/MyLogoutHandler.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java (89%) rename {springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt => springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway}/Token.java (91%) rename {springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt => springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway}/TokenContext.java (91%) create mode 100644 springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway/TokenGateway.java create mode 100644 springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JWTSecurityConfiguration.java create mode 100644 springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JWTTokenGatewayImpl.java rename springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Jwt.java => springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JwtTokenGateway.java (78%) create mode 100644 springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/SecurityJWTProperties.java rename springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/properties/SecurityJwtProperties.java => springboot-starter-security/src/main/java/com/codingapi/springboot/security/properties/CodingApiSecurityProperties.java (69%) create mode 100644 springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisSecurityConfiguration.java create mode 100644 springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java create mode 100644 springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGatewayImpl.java create mode 100644 springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/SecurityRedisProperties.java create mode 100644 springboot-starter-security/src/main/resources/META-INF/spring.factories create mode 100644 springboot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename {springboot-starter-security-jwt => springboot-starter-security}/src/test/java/com/codingapi/springboot/security/SecurityJwtApplication.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/test/java/com/codingapi/springboot/security/SecurityJwtApplicationTest.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/test/java/com/codingapi/springboot/security/controller/DemoController.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/test/java/com/codingapi/springboot/security/jwt/TestVO.java (100%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/test/java/com/codingapi/springboot/security/jwt/TokenTest.java (73%) rename {springboot-starter-security-jwt => springboot-starter-security}/src/test/resources/application.properties (77%) diff --git a/README.md b/README.md index 16844a72..6b653203 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ v.3.x 为springboot 3.x版本,使用jdk17版本 * springboot-starter | Springboot领域驱动框架 * springboot-starter-data-fast | 快速数据呈现框架 -* springboot-starter-security-jwt | security&jwt权限框架 +* springboot-starter-security | security权限框架支持基于JWT的无状态权限认证与Redis的有状态权限认证 ## SpringBoot DDD Architecture | SpringBoot DDD 框架图 @@ -44,7 +44,7 @@ v.3.x 为springboot 3.x版本,使用jdk17版本 com.codingapi.springboot - springboot-starter-security-jwt + springboot-starter-security ${last.version} diff --git a/docs/wiki/springboot-starter-security-jwt.md b/docs/wiki/springboot-starter-security.md similarity index 79% rename from docs/wiki/springboot-starter-security-jwt.md rename to docs/wiki/springboot-starter-security.md index d7c71b5b..d33c5c4a 100644 --- a/docs/wiki/springboot-starter-security-jwt.md +++ b/docs/wiki/springboot-starter-security.md @@ -1,18 +1,28 @@ -springboot-starter-security-jwt 功能介绍 +springboot-starter-security 功能介绍 + +支持无状态的JWT和有状态的redis两种不同的token机制 配置文件,默认参数即说明 ```properties +# JWT开关 +codingapi.security.jwt.enable=true # JWT密钥 需大于32位的字符串 -codingapi.security.jwt-secret=codingapi.security.jwt.secretkey +codingapi.security.jwt.secret-key=codingapi.security.jwt.secretkey + +# JWT 有效时间(毫秒) 15分钟有效期 1000*60*15=900000 +codingapi.security.jwt.valid-time=900000 +# JWT 更换令牌时间(毫秒) 10分钟后更换令牌 1000*60*10=600000 +codingapi.security.jwt.rest-time=600000 + # JWT AES密钥 codingapi.security.ase-key=QUNEWCQlXiYqJCNYQ1phc0FDRFgkJV4mKiQjWENaYXM= # JWT AES IV -codingapi.security.aes-iv=QUNYRkdIQEVEUyNYQ1phcw== +codingapi.security.ase-iv=QUNYRkdIQEVEUyNYQ1phcw== -# JWT 有效时间(毫秒) 15分钟有效期 1000*60*15=900000 -codingapi.security.jwt-time=900000 -# JWT 更换令牌时间(毫秒) 10分钟后更换令牌 1000*60*10=600000 -codingapi.security.jwt-rest-time=600000 +# Redis开关 +#codingapi.security.redis.enable=true +#spring.data.redis.host=localhost +#spring.data.redis.port=6379 # Security 配置 请求权限拦截地址 codingapi.security.authenticated-urls=/api/** @@ -52,7 +62,7 @@ security默认的账户密码为admin/admin,可以通过重写UserDetailsServi ## 登录拦截 可以通过重写SecurityLoginHandler来实现自定义登录拦截,preHandle登录前的拦截处理,postHandle登录后的拦截处理 -```java +``` @Bean public SecurityLoginHandler securityLoginHandler() { return new SecurityLoginHandler() { @@ -74,15 +84,15 @@ security默认的账户密码为admin/admin,可以通过重写UserDetailsServi 通过TokenContext获取当前用户信息 ```java @GetMapping("/user") - public String user(){ - return TokenContext.current().getUsername(); - } +public String user(){ + return TokenContext.current().getUsername(); +} ``` 可以通过Token的extra字段来存储用户的更多信息,然后通过TokenContext获取 ```java @GetMapping("/user") - public String user(){ - return TokenContext.current().getExtra("user"); - } +public String user(){ + return TokenContext.current().getExtra("user"); +} ``` diff --git a/pom.xml b/pom.xml index 17d00ac7..6bcb044d 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.7.10 + 2.8.0 https://github.com/codingapi/springboot-framewrok springboot-parent @@ -32,7 +32,7 @@ 3.1.0 ${project.version} 2.0.42 - 0.12.3 + 0.12.5 2.15.0 1.8.1 1.11.0 @@ -143,7 +143,7 @@ com.codingapi.springboot - springboot-starter-security-jwt + springboot-starter-security ${codingapi.framework.version} @@ -249,7 +249,7 @@ springboot-starter - springboot-starter-security-jwt + springboot-starter-security springboot-starter-data-fast @@ -260,7 +260,7 @@ springboot-starter - springboot-starter-security-jwt + springboot-starter-security springboot-starter-data-fast @@ -309,7 +309,7 @@ springboot-starter - springboot-starter-security-jwt + springboot-starter-security springboot-starter-data-fast diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index dba73ff4..027c6057 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.7.10 + 2.8.0 4.0.0 diff --git a/springboot-starter-security-jwt/src/main/resources/META-INF/spring.factories b/springboot-starter-security-jwt/src/main/resources/META-INF/spring.factories deleted file mode 100644 index b7882c59..00000000 --- a/springboot-starter-security-jwt/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,4 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.codingapi.springboot.security.configurer.WebSecurityConfigurer,\ -com.codingapi.springboot.security.crypto.MyCryptoConfiguration,\ -com.codingapi.springboot.security.AutoConfiguration \ No newline at end of file diff --git a/springboot-starter-security-jwt/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/springboot-starter-security-jwt/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 69b9af0d..00000000 --- a/springboot-starter-security-jwt/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1,3 +0,0 @@ -com.codingapi.springboot.security.configurer.WebSecurityConfigurer -com.codingapi.springboot.security.crypto.MyCryptoConfiguration -com.codingapi.springboot.security.AutoConfiguration \ No newline at end of file diff --git a/springboot-starter-security-jwt/pom.xml b/springboot-starter-security/pom.xml similarity index 73% rename from springboot-starter-security-jwt/pom.xml rename to springboot-starter-security/pom.xml index 73c3f64f..f7f43525 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,13 +6,13 @@ springboot-parent com.codingapi.springboot - 2.7.10 + 2.8.0 - springboot-starter-security-jwt + springboot-starter-security - springboot-starter-security-jwt - springboot-starter-security-jwt project for Spring Boot + springboot-starter-security + springboot-starter-security project for Spring Boot 8 @@ -30,19 +30,28 @@ spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-data-redis + provided + + io.jsonwebtoken jjwt-api + provided io.jsonwebtoken jjwt-impl + provided io.jsonwebtoken jjwt-jackson + provided diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java similarity index 86% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java index fb557e55..27c81da9 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java @@ -4,9 +4,9 @@ import com.codingapi.springboot.security.controller.VersionController; import com.codingapi.springboot.security.dto.request.LoginRequest; import com.codingapi.springboot.security.filter.*; -import com.codingapi.springboot.security.jwt.Jwt; -import com.codingapi.springboot.security.jwt.Token; -import com.codingapi.springboot.security.properties.SecurityJwtProperties; +import com.codingapi.springboot.security.gateway.Token; +import com.codingapi.springboot.security.gateway.TokenGateway; +import com.codingapi.springboot.security.properties.CodingApiSecurityProperties; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -86,8 +86,8 @@ public void postHandle(HttpServletRequest request, HttpServletResponse response, @Bean @ConditionalOnMissingBean - public SecurityFilterChain filterChain(HttpSecurity security, Jwt jwt, SecurityLoginHandler loginHandler, - SecurityJwtProperties properties, AuthenticationTokenFilter authenticationTokenFilter) throws Exception { + public SecurityFilterChain filterChain(HttpSecurity security, TokenGateway tokenGateway, SecurityLoginHandler loginHandler, + CodingApiSecurityProperties properties, AuthenticationTokenFilter authenticationTokenFilter) throws Exception { //disable basic auth security.httpBasic().disable(); @@ -96,7 +96,7 @@ public SecurityFilterChain filterChain(HttpSecurity security, Jwt jwt, SecurityL if (properties.isDisableCsrf()) { security.csrf().disable(); } - security.apply(new HttpSecurityConfigurer(jwt, loginHandler, properties, authenticationTokenFilter)); + security.apply(new HttpSecurityConfigurer(tokenGateway, loginHandler, properties, authenticationTokenFilter)); security .exceptionHandling() .authenticationEntryPoint(new MyUnAuthenticationEntryPoint()) @@ -135,19 +135,13 @@ public AuthenticationProvider authenticationProvider(UserDetailsService userDeta } - @Bean - @ConditionalOnMissingBean - public Jwt jwt(SecurityJwtProperties properties) { - return new Jwt(properties.getJwtSecretKey(), properties.getJwtTime(), properties.getJwtRestTime()); - } - @Bean - public WebMvcConfigurer corsConfigurer(SecurityJwtProperties securityJwtProperties) { + public WebMvcConfigurer corsConfigurer(CodingApiSecurityProperties securityProperties) { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { - if (securityJwtProperties.isDisableCors()) { + if (securityProperties.isDisableCors()) { registry.addMapping("/**") .allowedHeaders("*") .allowedMethods("*") @@ -164,8 +158,8 @@ public void addCorsMappings(CorsRegistry registry) { @Bean @ConfigurationProperties(prefix = "codingapi.security") - public SecurityJwtProperties securityJwtProperties() { - return new SecurityJwtProperties(); + public CodingApiSecurityProperties codingApiSecurityProperties() { + return new CodingApiSecurityProperties(); } diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java similarity index 72% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java index c95ec34e..e6258f1c 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java @@ -4,8 +4,8 @@ import com.codingapi.springboot.security.filter.MyAuthenticationFilter; import com.codingapi.springboot.security.filter.MyLoginFilter; import com.codingapi.springboot.security.filter.SecurityLoginHandler; -import com.codingapi.springboot.security.jwt.Jwt; -import com.codingapi.springboot.security.properties.SecurityJwtProperties; +import com.codingapi.springboot.security.gateway.TokenGateway; +import com.codingapi.springboot.security.properties.CodingApiSecurityProperties; import lombok.AllArgsConstructor; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -14,16 +14,16 @@ @AllArgsConstructor public class HttpSecurityConfigurer extends AbstractHttpConfigurer { - private final Jwt jwt; + private final TokenGateway tokenGateway; private final SecurityLoginHandler securityLoginHandler; - private final SecurityJwtProperties securityJwtProperties; + private final CodingApiSecurityProperties securityProperties; private final AuthenticationTokenFilter authenticationTokenFilter; @Override public void configure(HttpSecurity security) throws Exception { AuthenticationManager manager = security.getSharedObject(AuthenticationManager.class); - security.addFilter(new MyLoginFilter(manager, jwt,securityLoginHandler, securityJwtProperties)); - security.addFilter(new MyAuthenticationFilter(manager,securityJwtProperties,jwt,authenticationTokenFilter)); + security.addFilter(new MyLoginFilter(manager, tokenGateway,securityLoginHandler, securityProperties)); + security.addFilter(new MyAuthenticationFilter(manager,securityProperties,tokenGateway,authenticationTokenFilter)); } } diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/WebSecurityConfigurer.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/configurer/WebSecurityConfigurer.java similarity index 71% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/WebSecurityConfigurer.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/configurer/WebSecurityConfigurer.java index 5bd1ebd5..06d84d7c 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/WebSecurityConfigurer.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/configurer/WebSecurityConfigurer.java @@ -1,6 +1,6 @@ package com.codingapi.springboot.security.configurer; -import com.codingapi.springboot.security.properties.SecurityJwtProperties; +import com.codingapi.springboot.security.properties.CodingApiSecurityProperties; import lombok.AllArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.WebSecurity; @@ -10,12 +10,12 @@ @AllArgsConstructor public class WebSecurityConfigurer implements WebSecurityCustomizer { - private final SecurityJwtProperties securityJwtProperties; + private final CodingApiSecurityProperties securityProperties; @Override public void customize(WebSecurity web) { //ignoring security filters request url - web.ignoring().antMatchers(securityJwtProperties.getIgnoreUrls()); + web.ignoring().antMatchers(securityProperties.getIgnoreUrls()); } } diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/controller/VersionController.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/controller/VersionController.java similarity index 100% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/controller/VersionController.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/controller/VersionController.java diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/crypto/MyAES.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/crypto/AESTools.java similarity index 84% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/crypto/MyAES.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/crypto/AESTools.java index b3536ca8..efe4a7a8 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/crypto/MyAES.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/crypto/AESTools.java @@ -6,20 +6,20 @@ import java.nio.charset.StandardCharsets; import java.util.Base64; -public class MyAES { +public class AESTools { - private final static MyAES instance = new MyAES(); + private final static AESTools instance = new AESTools(); private AES aes; - private MyAES() { + private AESTools() { } void init(AES aes) { this.aes = aes; } - public static MyAES getInstance() { + public static AESTools getInstance() { return instance; } diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/crypto/MyCryptoConfiguration.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/crypto/SecurityCryptoConfiguration.java similarity index 69% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/crypto/MyCryptoConfiguration.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/crypto/SecurityCryptoConfiguration.java index 0d4b2bd4..6820dc5c 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/crypto/MyCryptoConfiguration.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/crypto/SecurityCryptoConfiguration.java @@ -1,7 +1,7 @@ package com.codingapi.springboot.security.crypto; import com.codingapi.springboot.framework.crypto.AES; -import com.codingapi.springboot.security.properties.SecurityJwtProperties; +import com.codingapi.springboot.security.properties.CodingApiSecurityProperties; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -9,15 +9,14 @@ import java.util.Base64; @Configuration -public class MyCryptoConfiguration { +public class SecurityCryptoConfiguration { @Bean @ConditionalOnMissingBean - public AES aes(SecurityJwtProperties properties) throws Exception { + public AES aes(CodingApiSecurityProperties properties) throws Exception { AES aes = new AES(Base64.getDecoder().decode(properties.getAseKey().getBytes()), Base64.getDecoder().decode(properties.getAseIv())); - MyAES.getInstance().init(aes); + AESTools.getInstance().init(aes); return aes; } - } diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/dto/request/LoginRequest.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/dto/request/LoginRequest.java similarity index 100% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/dto/request/LoginRequest.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/dto/request/LoginRequest.java diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/dto/request/LoginRequestContext.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/dto/request/LoginRequestContext.java similarity index 100% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/dto/request/LoginRequestContext.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/dto/request/LoginRequestContext.java diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/dto/response/LoginResponse.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/dto/response/LoginResponse.java similarity index 100% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/dto/response/LoginResponse.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/dto/response/LoginResponse.java diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/exception/TokenExpiredException.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/exception/TokenExpiredException.java similarity index 100% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/exception/TokenExpiredException.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/exception/TokenExpiredException.java diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java similarity index 100% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java similarity index 100% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java similarity index 77% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java index c326bd75..1b7286cf 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java @@ -3,9 +3,9 @@ import com.alibaba.fastjson.JSONObject; import com.codingapi.springboot.framework.dto.response.Response; import com.codingapi.springboot.security.exception.TokenExpiredException; -import com.codingapi.springboot.security.jwt.Jwt; -import com.codingapi.springboot.security.jwt.Token; -import com.codingapi.springboot.security.properties.SecurityJwtProperties; +import com.codingapi.springboot.security.gateway.Token; +import com.codingapi.springboot.security.gateway.TokenGateway; +import com.codingapi.springboot.security.properties.CodingApiSecurityProperties; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.springframework.security.authentication.AuthenticationManager; @@ -26,16 +26,16 @@ public class MyAuthenticationFilter extends BasicAuthenticationFilter { private final static String TOKEN_KEY = "Authorization"; - private final Jwt jwt; + private final TokenGateway tokenGateway; - private final SecurityJwtProperties securityJwtProperties; + private final CodingApiSecurityProperties securityProperties; private final AuthenticationTokenFilter authenticationTokenFilter; private final AntPathMatcher antPathMatcher = new AntPathMatcher(); - public MyAuthenticationFilter(AuthenticationManager manager, SecurityJwtProperties securityJwtProperties, Jwt jwt,AuthenticationTokenFilter authenticationTokenFilter) { + public MyAuthenticationFilter(AuthenticationManager manager, CodingApiSecurityProperties securityProperties, TokenGateway tokenGateway,AuthenticationTokenFilter authenticationTokenFilter) { super(manager); - this.jwt = jwt; - this.securityJwtProperties = securityJwtProperties; + this.tokenGateway = tokenGateway; + this.securityProperties = securityProperties; this.authenticationTokenFilter = authenticationTokenFilter; } @@ -43,7 +43,7 @@ public MyAuthenticationFilter(AuthenticationManager manager, SecurityJwtProperti @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { log.debug("token authentication ~"); - for (String antUrl : securityJwtProperties.getAuthenticatedUrls()) { + for (String antUrl : securityProperties.getAuthenticatedUrls()) { if(antPathMatcher.match(antUrl,request.getRequestURI())) { String sign = request.getHeader(TOKEN_KEY); @@ -52,9 +52,9 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse return; } - Token token = jwt.parser(sign); + Token token = tokenGateway.parser(sign); if (token.canRestToken()) { - Token newSign = jwt.create(token.getUsername(), token.decodeIv(), token.getAuthorities(), token.getExtra()); + Token newSign = tokenGateway.create(token.getUsername(), token.decodeIv(), token.getAuthorities(), token.getExtra()); log.info("reset token "); response.setHeader(TOKEN_KEY, newSign.getToken()); } diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java similarity index 87% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java index 27c1bfb9..2bf4ab52 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java @@ -6,10 +6,10 @@ import com.codingapi.springboot.security.dto.request.LoginRequest; import com.codingapi.springboot.security.dto.request.LoginRequestContext; import com.codingapi.springboot.security.dto.response.LoginResponse; -import com.codingapi.springboot.security.jwt.Jwt; -import com.codingapi.springboot.security.jwt.Token; -import com.codingapi.springboot.security.jwt.TokenContext; -import com.codingapi.springboot.security.properties.SecurityJwtProperties; +import com.codingapi.springboot.security.gateway.Token; +import com.codingapi.springboot.security.gateway.TokenContext; +import com.codingapi.springboot.security.gateway.TokenGateway; +import com.codingapi.springboot.security.properties.CodingApiSecurityProperties; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.springframework.security.authentication.AuthenticationManager; @@ -33,15 +33,15 @@ @Slf4j public class MyLoginFilter extends UsernamePasswordAuthenticationFilter { - private final Jwt jwt; + private final TokenGateway tokenGateway; private final SecurityLoginHandler loginHandler; - public MyLoginFilter(AuthenticationManager authenticationManager, Jwt jwt, SecurityLoginHandler loginHandler, SecurityJwtProperties securityJwtProperties) { + public MyLoginFilter(AuthenticationManager authenticationManager, TokenGateway tokenGateway, SecurityLoginHandler loginHandler, CodingApiSecurityProperties securityProperties) { super(authenticationManager); - this.jwt = jwt; + this.tokenGateway = tokenGateway; this.loginHandler = loginHandler; - this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(securityJwtProperties.getLoginProcessingUrl(), "POST")); + this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(securityProperties.getLoginProcessingUrl(), "POST")); } @Override @@ -72,7 +72,7 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR User user = (User) authResult.getPrincipal(); LoginRequest loginRequest = LoginRequestContext.getInstance().get(); - Token token = jwt.create(user.getUsername(), loginRequest.getPassword(), + Token token = tokenGateway.create(user.getUsername(), loginRequest.getPassword(), user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()), TokenContext.getExtra()); diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutHandler.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLogoutHandler.java similarity index 100% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutHandler.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLogoutHandler.java diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java similarity index 100% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java similarity index 100% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java similarity index 89% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java index 8c375480..97de8972 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java @@ -1,7 +1,7 @@ package com.codingapi.springboot.security.filter; import com.codingapi.springboot.security.dto.request.LoginRequest; -import com.codingapi.springboot.security.jwt.Token; +import com.codingapi.springboot.security.gateway.Token; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Token.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway/Token.java similarity index 91% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Token.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway/Token.java index a3fd6345..9579a9b3 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Token.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway/Token.java @@ -1,8 +1,8 @@ -package com.codingapi.springboot.security.jwt; +package com.codingapi.springboot.security.gateway; import com.alibaba.fastjson.JSONObject; import com.codingapi.springboot.framework.serializable.JsonSerializable; -import com.codingapi.springboot.security.crypto.MyAES; +import com.codingapi.springboot.security.crypto.AESTools; import com.codingapi.springboot.security.exception.TokenExpiredException; import lombok.Getter; import lombok.NoArgsConstructor; @@ -34,7 +34,7 @@ public Token(String username, String iv,String extra, List authorities, this.username = username; this.extra = extra; if(iv!=null) { - this.iv = MyAES.getInstance().encode(iv); + this.iv = AESTools.getInstance().encode(iv); } this.authorities = authorities; this.expireTime = System.currentTimeMillis() + expireValue; @@ -56,7 +56,7 @@ public String decodeIv(){ if(iv==null){ return null; } - return MyAES.getInstance().decode(iv); + return AESTools.getInstance().decode(iv); } diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/TokenContext.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway/TokenContext.java similarity index 91% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/TokenContext.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway/TokenContext.java index 99b37a7c..e3ecaa8f 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/TokenContext.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway/TokenContext.java @@ -1,4 +1,4 @@ -package com.codingapi.springboot.security.jwt; +package com.codingapi.springboot.security.gateway; import org.springframework.security.core.context.SecurityContextHolder; diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway/TokenGateway.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway/TokenGateway.java new file mode 100644 index 00000000..b339079d --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/gateway/TokenGateway.java @@ -0,0 +1,23 @@ +package com.codingapi.springboot.security.gateway; + +import java.util.List; + +public interface TokenGateway { + + Token create(String username, String iv, List authorities, String extra); + + default Token create(String username, String iv, List authorities) { + return create(username, iv, authorities, null); + } + + default Token create(String username, List authorities) { + return create(username, null, authorities, null); + } + + default Token create(String username, List authorities, String extra) { + return create(username, null, authorities, extra); + } + + Token parser(String sign); + +} diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JWTSecurityConfiguration.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JWTSecurityConfiguration.java new file mode 100644 index 00000000..54df5b3c --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JWTSecurityConfiguration.java @@ -0,0 +1,35 @@ +package com.codingapi.springboot.security.jwt; + +import com.codingapi.springboot.security.gateway.TokenGateway; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnProperty(prefix = "codingapi.security.jwt", name = "enable", havingValue = "true") +public class JWTSecurityConfiguration { + + + @Bean + @ConfigurationProperties(prefix = "codingapi.security.jwt") + public SecurityJWTProperties securityJWTProperties() { + return new SecurityJWTProperties(); + } + + + @Bean + @ConditionalOnMissingBean + public JwtTokenGateway jwtTokenGateway(SecurityJWTProperties properties) { + return new JwtTokenGateway(properties); + } + + + @Bean + @ConditionalOnMissingBean + public TokenGateway jwtTokenGatewayImpl(JwtTokenGateway jwtTokenGateway) { + return new JWTTokenGatewayImpl(jwtTokenGateway); + } + +} diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JWTTokenGatewayImpl.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JWTTokenGatewayImpl.java new file mode 100644 index 00000000..4a890ab7 --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JWTTokenGatewayImpl.java @@ -0,0 +1,25 @@ +package com.codingapi.springboot.security.jwt; + +import com.codingapi.springboot.security.gateway.Token; +import com.codingapi.springboot.security.gateway.TokenGateway; + +import java.util.List; + +public class JWTTokenGatewayImpl implements TokenGateway { + + private final JwtTokenGateway jwtTokenGateway; + + public JWTTokenGatewayImpl(JwtTokenGateway jwtTokenGateway) { + this.jwtTokenGateway = jwtTokenGateway; + } + + @Override + public Token create(String username, String password, List authorities, String extra) { + return jwtTokenGateway.create(username, password, authorities, extra); + } + + @Override + public Token parser(String sign) { + return jwtTokenGateway.parser(sign); + } +} diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Jwt.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JwtTokenGateway.java similarity index 78% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Jwt.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JwtTokenGateway.java index 75f93713..57dab485 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Jwt.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/JwtTokenGateway.java @@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSONObject; import com.codingapi.springboot.framework.exception.LocaleMessageException; +import com.codingapi.springboot.security.gateway.Token; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; @@ -11,19 +12,19 @@ import java.nio.charset.StandardCharsets; import java.util.List; -public class Jwt { +public class JwtTokenGateway { private final SecretKey key; - private final int jwtTime; - private final int jwtRestTime; + private final int validTime; + private final int restTime; - public Jwt(String secretKey, int jwtTime, int jwtRestTime) { - this.key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); - this.jwtTime = jwtTime; - this.jwtRestTime = jwtRestTime; + public JwtTokenGateway(SecurityJWTProperties properties) { + this.key = Keys.hmacShaKeyFor(properties.getSecretKey().getBytes(StandardCharsets.UTF_8)); + this.validTime = properties.getValidTime(); + this.restTime = properties.getRestTime(); } - public Token create(String username, List authorities,String extra){ + public Token create(String username, List authorities, String extra){ return create(username, null,authorities, extra); } @@ -36,7 +37,7 @@ public Token create(String username, String iv, List authorities){ } public Token create(String username, String iv,List authorities,String extra){ - Token token = new Token(username, iv,extra, authorities, jwtTime, jwtRestTime); + Token token = new Token(username, iv,extra, authorities, validTime, restTime); String jwt = Jwts.builder().subject(token.toJson()).signWith(key).compact(); token.setToken(jwt); return token; @@ -54,4 +55,4 @@ public Token parser(String sign) { throw new LocaleMessageException("token.error", exp.getMessage()); } } -} \ No newline at end of file +} diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/SecurityJWTProperties.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/SecurityJWTProperties.java new file mode 100644 index 00000000..d4ca0537 --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/jwt/SecurityJWTProperties.java @@ -0,0 +1,35 @@ +package com.codingapi.springboot.security.jwt; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class SecurityJWTProperties { + + + /** + * 是否启用JWT + */ + private boolean enable = true; + + /** + * JWT密钥 + * 需大于32位的字符串 + */ + private String secretKey = "codingapi.security.jwt.secretkey"; + + + /** + * JWT 有效时间(毫秒) + * 15分钟有效期 1000*60*15=900000 + */ + private int validTime = 900000; + + /** + * JWT 更换令牌时间(毫秒) + * 10分钟后更换令牌 1000*60*10=600000 + */ + private int restTime = 600000; + +} diff --git a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/properties/SecurityJwtProperties.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/properties/CodingApiSecurityProperties.java similarity index 69% rename from springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/properties/SecurityJwtProperties.java rename to springboot-starter-security/src/main/java/com/codingapi/springboot/security/properties/CodingApiSecurityProperties.java index 5c296e80..4a33d91b 100644 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/properties/SecurityJwtProperties.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/properties/CodingApiSecurityProperties.java @@ -5,37 +5,7 @@ @Setter @Getter -public class SecurityJwtProperties { - - /** - * JWT密钥 - * 需大于32位的字符串 - */ - private String jwtSecretKey = "codingapi.security.jwt.secretkey"; - - - /** - * aes key - */ - private String aseKey = "QUNEWCQlXiYqJCNYQ1phc0FDRFgkJV4mKiQjWENaYXM="; - - /** - * aes iv - */ - private String aseIv = "QUNYRkdIQEVEUyNYQ1phcw=="; - - - /** - * JWT 有效时间(毫秒) - * 15分钟有效期 1000*60*15=900000 - */ - private int jwtTime = 900000; - - /** - * JWT 更换令牌时间(毫秒) - * 10分钟后更换令牌 1000*60*10=600000 - */ - private int jwtRestTime = 600000; +public class CodingApiSecurityProperties { /** * 权限拦截URL @@ -58,6 +28,17 @@ public class SecurityJwtProperties { */ private String ignoreUrls = "/open/**"; + /** + * aes key + */ + private String aseKey = "QUNEWCQlXiYqJCNYQ1phc0FDRFgkJV4mKiQjWENaYXM="; + + /** + * aes iv + */ + private String aseIv = "QUNYRkdIQEVEUyNYQ1phcw=="; + + /** * 启用禁用CSRF */ diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisSecurityConfiguration.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisSecurityConfiguration.java new file mode 100644 index 00000000..c4bf141b --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisSecurityConfiguration.java @@ -0,0 +1,35 @@ +package com.codingapi.springboot.security.redis; + +import com.codingapi.springboot.security.gateway.TokenGateway; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.RedisTemplate; + +@Configuration +@ConditionalOnProperty(prefix = "codingapi.security.redis", name = "enable", havingValue = "true") +public class RedisSecurityConfiguration { + + + @Bean + @ConfigurationProperties(prefix = "codingapi.security.redis") + public SecurityRedisProperties securityRedisProperties() { + return new SecurityRedisProperties(); + } + + + @Bean + @ConditionalOnMissingBean + public RedisTokenGateway redisTokenGateway(RedisTemplate redisTemplate, SecurityRedisProperties properties) { + return new RedisTokenGateway(redisTemplate, properties); + } + + @Bean + @ConditionalOnMissingBean + public TokenGateway redisTokenGatewayImpl(RedisTokenGateway redisTokenGateway) { + return new RedisTokenGatewayImpl(redisTokenGateway); + } + +} diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java new file mode 100644 index 00000000..d4eb4257 --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java @@ -0,0 +1,65 @@ +package com.codingapi.springboot.security.redis; + +import com.alibaba.fastjson2.JSONObject; +import com.codingapi.springboot.security.gateway.Token; +import org.springframework.data.redis.core.RedisTemplate; + +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; + +public class RedisTokenGateway { + + private final RedisTemplate redisTemplate; + private final int validTime; + private final int restTime; + + public RedisTokenGateway(RedisTemplate redisTemplate, SecurityRedisProperties properties) { + this.redisTemplate = redisTemplate; + this.validTime = properties.getValidTime(); + this.restTime = properties.getRestTime(); + } + + public Token create(String username, String iv, List authorities, String extra) { + Token token = new Token(username, iv, extra, authorities, validTime, restTime); + String key = String.format("%s:%s", username, UUID.randomUUID().toString().replaceAll("-", "")); + token.setToken(key); + redisTemplate.opsForValue().set(key, token.toJson(), validTime, TimeUnit.MILLISECONDS); + return token; + } + + public Token parser(String sign) { + String json = redisTemplate.opsForValue().get(sign); + if (json == null) { + return null; + } + return JSONObject.parseObject(json, Token.class); + } + + public void removeToken(String token) { + redisTemplate.delete(token); + } + + public void removeUsername(String username) { + Set keys = redisTemplate.keys(username + ":*"); + if (keys != null && !keys.isEmpty()) { + redisTemplate.delete(keys); + } + } + + public void removeUsername(String username, Predicate predicate) { + Set keys = redisTemplate.keys(username + ":*"); + if (keys != null && !keys.isEmpty()) { + for (String key : keys) { + Token token = parser(key); + if (token != null && predicate.test(token)) { + redisTemplate.delete(key); + } + } + } + } + + +} diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGatewayImpl.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGatewayImpl.java new file mode 100644 index 00000000..19453d66 --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGatewayImpl.java @@ -0,0 +1,26 @@ +package com.codingapi.springboot.security.redis; + +import com.codingapi.springboot.security.gateway.Token; +import com.codingapi.springboot.security.gateway.TokenGateway; + +import java.util.List; + +public class RedisTokenGatewayImpl implements TokenGateway { + + private final RedisTokenGateway redisTokenGateway; + + public RedisTokenGatewayImpl(RedisTokenGateway redisTokenGateway) { + this.redisTokenGateway = redisTokenGateway; + } + + @Override + public Token create(String username, String iv, List authorities, String extra) { + return redisTokenGateway.create(username, iv, authorities, extra); + } + + @Override + public Token parser(String sign) { + return redisTokenGateway.parser(sign); + } + +} diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/SecurityRedisProperties.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/SecurityRedisProperties.java new file mode 100644 index 00000000..14eae9ac --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/SecurityRedisProperties.java @@ -0,0 +1,27 @@ +package com.codingapi.springboot.security.redis; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class SecurityRedisProperties { + + + /** + * 是否启用redis + */ + private boolean enable = true; + + /** + * 15分钟有效期 1000*60*15=900000 + */ + private int validTime = 900000; + + /** + * 10分钟后更换令牌 1000*60*10=600000 + */ + private int restTime = 600000; + + +} diff --git a/springboot-starter-security/src/main/resources/META-INF/spring.factories b/springboot-starter-security/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..6fbb976a --- /dev/null +++ b/springboot-starter-security/src/main/resources/META-INF/spring.factories @@ -0,0 +1,6 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +com.codingapi.springboot.security.configurer.WebSecurityConfigurer,\ +com.codingapi.springboot.security.crypto.SecurityCryptoConfiguration,\ +com.codingapi.springboot.security.jwt.JWTSecurityConfiguration,\ +com.codingapi.springboot.security.redis.RedisSecurityConfiguration,\ +com.codingapi.springboot.security.AutoConfiguration \ No newline at end of file diff --git a/springboot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/springboot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..59324754 --- /dev/null +++ b/springboot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,5 @@ +com.codingapi.springboot.security.configurer.WebSecurityConfigurer +com.codingapi.springboot.security.crypto.SecurityCryptoConfiguration +com.codingapi.springboot.security.jwt.JWTSecurityConfiguration +com.codingapi.springboot.security.redis.RedisSecurityConfiguration +com.codingapi.springboot.security.AutoConfiguration \ No newline at end of file diff --git a/springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/SecurityJwtApplication.java b/springboot-starter-security/src/test/java/com/codingapi/springboot/security/SecurityJwtApplication.java similarity index 100% rename from springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/SecurityJwtApplication.java rename to springboot-starter-security/src/test/java/com/codingapi/springboot/security/SecurityJwtApplication.java diff --git a/springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/SecurityJwtApplicationTest.java b/springboot-starter-security/src/test/java/com/codingapi/springboot/security/SecurityJwtApplicationTest.java similarity index 100% rename from springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/SecurityJwtApplicationTest.java rename to springboot-starter-security/src/test/java/com/codingapi/springboot/security/SecurityJwtApplicationTest.java diff --git a/springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/controller/DemoController.java b/springboot-starter-security/src/test/java/com/codingapi/springboot/security/controller/DemoController.java similarity index 100% rename from springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/controller/DemoController.java rename to springboot-starter-security/src/test/java/com/codingapi/springboot/security/controller/DemoController.java diff --git a/springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/jwt/TestVO.java b/springboot-starter-security/src/test/java/com/codingapi/springboot/security/jwt/TestVO.java similarity index 100% rename from springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/jwt/TestVO.java rename to springboot-starter-security/src/test/java/com/codingapi/springboot/security/jwt/TestVO.java diff --git a/springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/jwt/TokenTest.java b/springboot-starter-security/src/test/java/com/codingapi/springboot/security/jwt/TokenTest.java similarity index 73% rename from springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/jwt/TokenTest.java rename to springboot-starter-security/src/test/java/com/codingapi/springboot/security/jwt/TokenTest.java index 3010f7fb..b5611674 100644 --- a/springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/jwt/TokenTest.java +++ b/springboot-starter-security/src/test/java/com/codingapi/springboot/security/jwt/TokenTest.java @@ -1,6 +1,8 @@ package com.codingapi.springboot.security.jwt; import com.codingapi.springboot.security.exception.TokenExpiredException; +import com.codingapi.springboot.security.gateway.Token; +import com.codingapi.springboot.security.gateway.TokenGateway; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -14,7 +16,7 @@ class TokenTest { @Autowired - private Jwt jwt; + private TokenGateway tokenGateway; @Test void verify1() throws TokenExpiredException { @@ -22,10 +24,10 @@ void verify1() throws TokenExpiredException { String iv = "123456"; List authorities = Collections.singletonList("ADMIN"); - Token token =jwt.create(username,iv,authorities); + Token token =tokenGateway.create(username,iv,authorities); token.verify(); - Token data = jwt.parser(token.getToken()); + Token data = tokenGateway.parser(token.getToken()); assertEquals(data.decodeIv(),iv); assertEquals(data.getAuthorities(),authorities); } @@ -35,10 +37,10 @@ void verify2() throws TokenExpiredException { String username = "admin"; List authorities = Collections.singletonList("ADMIN"); - Token token =jwt.create(username,authorities); + Token token =tokenGateway.create(username,authorities); token.verify(); - Token data = jwt.parser(token.getToken()); + Token data = tokenGateway.parser(token.getToken()); assertEquals(data.getUsername(),username); assertEquals(data.getAuthorities(),authorities); } @@ -52,10 +54,10 @@ void verify3() throws TokenExpiredException { String extra = testVO.toJson(); List authorities = Collections.singletonList("ADMIN"); - Token token =jwt.create(username,authorities,extra); + Token token =tokenGateway.create(username,authorities,extra); token.verify(); - Token data = jwt.parser(token.getToken()); + Token data = tokenGateway.parser(token.getToken()); assertEquals(data.parseExtra(TestVO.class).getName(), testVO.getName()); assertEquals(data.getAuthorities(),authorities); } diff --git a/springboot-starter-security-jwt/src/test/resources/application.properties b/springboot-starter-security/src/test/resources/application.properties similarity index 77% rename from springboot-starter-security-jwt/src/test/resources/application.properties rename to springboot-starter-security/src/test/resources/application.properties index 3848c355..d228eabb 100644 --- a/springboot-starter-security-jwt/src/test/resources/application.properties +++ b/springboot-starter-security/src/test/resources/application.properties @@ -1,14 +1,16 @@ server.port=8088 -codingapi.security.jwt-time=10000 -codingapi.security.jwt-rest-time=5000 +codingapi.security.jwt.valid-time=10000 +codingapi.security.jwt.rest-time=5000 + +codingapi.security.jwt.enable=true # JWT密钥 需大于32位的字符串 -codingapi.security.jwt-secret=codingapi.security.jwt.secretkey +codingapi.security.jwt.secret-key=codingapi.security.jwt.secretkey # JWT AES密钥 codingapi.security.ase-key=QUNEWCQlXiYqJCNYQ1phc0FDRFgkJV4mKiQjWENaYXM= # JWT AES IV -codingapi.security.aes-iv=QUNYRkdIQEVEUyNYQ1phcw== +codingapi.security.ase-iv=QUNYRkdIQEVEUyNYQ1phcw== # JWT 有效时间(毫秒) 15分钟有效期 1000*60*15=900000 #codingapi.security.jwt-time=900000 diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 1cf03f54..386380dd 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.7.10 + 2.8.0 springboot-starter From d3c988d86af48b930dfce3d9ace6655df9abe15b Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Wed, 24 Apr 2024 11:00:29 +0800 Subject: [PATCH 041/129] #44 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/dto/request/SearchRequest.java | 81 +++++++++++++++---- 5 files changed, 70 insertions(+), 19 deletions(-) diff --git a/pom.xml b/pom.xml index 6bcb044d..631d99da 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.0 + 2.8.1 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 027c6057..d2ff620f 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.0 + 2.8.1 4.0.0 diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index f7f43525..b850a475 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.0 + 2.8.1 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 386380dd..cc8b7b28 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.0 + 2.8.1 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java index 07c53bdd..2e95c80f 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java @@ -3,6 +3,8 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import lombok.Getter; +import lombok.Setter; import org.springframework.data.domain.Sort; import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestContextHolder; @@ -12,9 +14,7 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Base64; -import java.util.Enumeration; import java.util.List; -import java.util.stream.Collectors; /** * HttpServletRequest 请求参数解析成 PageRequest对象 @@ -46,17 +46,21 @@ public void setPageSize(int pageSize) { this.removeKeys.add("pageSize"); } - private String decode(String value) { - return new String(Base64.getDecoder().decode(value)); - } - - public void addSort(Sort sort) { pageRequest.addSort(sort); } public void removeFilter(String key) { pageRequest.removeFilter(key); + this.removeKeys.add(key); + } + + public String getParameter(String key) { + return request.getParameter(key); + } + + public String[] getParameterValues(String key) { + return request.getParameterValues(key); } public PageRequest addFilter(String key, Relation relation, Object... value) { @@ -75,6 +79,12 @@ public PageRequest orFilters(Filter... filters) { return pageRequest.orFilters(filters); } + + private String decode(String value) { + return new String(Base64.getDecoder().decode(value)); + } + + static class ClassContent { private final Class clazz; @@ -85,6 +95,12 @@ public ClassContent(Class clazz, PageRequest pageRequest) { this.pageRequest = pageRequest; } + public void addFilter(String key, Relation relation, String value) { + Class keyClass = getKeyType(key); + Object v = parseObject(value, keyClass); + pageRequest.addFilter(key, relation, v); + } + public void addFilter(String key, String value) { Class keyClass = getKeyType(key); Object v = parseObject(value, keyClass); @@ -92,7 +108,7 @@ public void addFilter(String key, String value) { } private Object parseObject(String value, Class keyClass) { - if(value.getClass().equals(keyClass)) { + if (value.getClass().equals(keyClass)) { return value; } return JSON.parseObject(value, keyClass); @@ -124,12 +140,37 @@ private Class getKeyType(String key) { } + @Setter + @Getter + static class ParamOperation { + private String key; + private String type; + + public Relation getOperation() { + return Relation.valueOf(type); + } + } + + private List loadParamOperations() { + String params = request.getParameter("params"); + if (StringUtils.hasLength(params)) { + params = decode(params); + if (JSON.isValid(params)) { + removeKeys.add("params"); + return JSON.parseArray(params, ParamOperation.class); + } + } + return null; + } + public PageRequest toPageRequest(Class clazz) { pageRequest.setCurrent(current); pageRequest.setPageSize(pageSize); ClassContent content = new ClassContent(clazz, pageRequest); + List loadParams = loadParamOperations(); + String sort = request.getParameter("sort"); if (StringUtils.hasLength(sort)) { sort = decode(sort); @@ -157,24 +198,34 @@ public PageRequest toPageRequest(Class clazz) { for (String key : jsonObject.keySet()) { JSONArray value = jsonObject.getJSONArray(key); if (value != null && !value.isEmpty()) { - List values = value.stream().map(Object::toString).collect(Collectors.toList()); + List values = value.stream().map(Object::toString).toList(); content.addFilter(key, values); } } } } - Enumeration enumeration = request.getParameterNames(); - while (enumeration.hasMoreElements()) { - String key = enumeration.nextElement(); + + request.getParameterNames().asIterator().forEachRemaining(key -> { if (!removeKeys.contains(key)) { String value = request.getParameter(key); if (StringUtils.hasLength(value)) { - content.addFilter(key, value); + if (loadParams != null) { + ParamOperation operation = loadParams.stream() + .filter(paramOperation -> paramOperation.getKey().equals(key)) + .findFirst() + .orElse(null); + if (operation != null) { + content.addFilter(key, operation.getOperation(), value); + } else { + content.addFilter(key, value); + } + } else { + content.addFilter(key, value); + } } } - } - + }); return pageRequest; } From e07f982793e4a0b2798255f5117de17a3234ac38 Mon Sep 17 00:00:00 2001 From: xlorne <1991wangliang@gmail.com> Date: Thu, 6 Jun 2024 11:37:18 +0800 Subject: [PATCH 042/129] add SearchRequest getParameterNames --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/dto/request/SearchRequest.java | 13 +++++++++++++ 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 631d99da..8d05b1a1 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.1 + 2.8.2 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index d2ff620f..23fd9270 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.1 + 2.8.2 4.0.0 diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index b850a475..4912e175 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.1 + 2.8.2 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index cc8b7b28..911d6cc0 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.1 + 2.8.2 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java index 2e95c80f..c6bc6f60 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java @@ -14,6 +14,7 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Base64; +import java.util.Enumeration; import java.util.List; /** @@ -21,7 +22,9 @@ */ public class SearchRequest { + @Getter private int current; + @Getter private int pageSize; private final HttpServletRequest request; @@ -63,6 +66,16 @@ public String[] getParameterValues(String key) { return request.getParameterValues(key); } + + public List getParameterNames() { + Enumeration enumeration = request.getParameterNames(); + List list = new ArrayList<>(); + while (enumeration.hasMoreElements()) { + list.add(enumeration.nextElement()); + } + return list; + } + public PageRequest addFilter(String key, Relation relation, Object... value) { return pageRequest.addFilter(key, relation, value); } From 9c726e3c8aa7ac2a013606b3ced65f15ea6d5fa7 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 17 Jun 2024 21:19:19 +0800 Subject: [PATCH 043/129] update 2.8.3 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 4 ++-- .../springboot/fast/DataFastConfiguration.java | 13 +++++++------ ...ingRegister.java => FastMvcMappingRegister.java} | 2 +- ...Register.java => FastScriptMappingRegister.java} | 6 +++--- springboot-starter-security/pom.xml | 2 +- .../springboot/security/AutoConfiguration.java | 11 ++++++++--- .../security/dto/response/LoginResponse.java | 1 + .../security/filter/AuthenticationTokenFilter.java | 5 +++-- .../security/filter/MyAuthenticationFilter.java | 2 +- .../springboot/security/filter/MyLoginFilter.java | 9 ++------- .../security/filter/SecurityLoginHandler.java | 5 +++-- springboot-starter/pom.xml | 2 +- 13 files changed, 34 insertions(+), 30 deletions(-) rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/{MvcMappingRegister.java => FastMvcMappingRegister.java} (98%) rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/{ScriptMappingRegister.java => FastScriptMappingRegister.java} (85%) diff --git a/pom.xml b/pom.xml index 8d05b1a1..4f2e3de7 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.2 + 2.8.3 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 23fd9270..b366a0b8 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.2 + 2.8.3 4.0.0 @@ -67,4 +67,4 @@ - \ No newline at end of file + diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java index 2fb91bcd..33136595 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/DataFastConfiguration.java @@ -1,8 +1,9 @@ package com.codingapi.springboot.fast; import com.codingapi.springboot.fast.manager.EntityManagerInitializer; -import com.codingapi.springboot.fast.mapping.MvcMappingRegister; -import com.codingapi.springboot.fast.script.ScriptMappingRegister; +import com.codingapi.springboot.fast.mapping.FastMvcMappingRegister; +import com.codingapi.springboot.fast.script.FastScriptMappingRegister; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; @@ -19,8 +20,8 @@ public class DataFastConfiguration { @Bean @ConditionalOnMissingBean - public MvcMappingRegister mvcMappingRegister(RequestMappingHandlerMapping handlerMapping) { - return new MvcMappingRegister(handlerMapping); + public FastMvcMappingRegister mvcMappingRegister(@Qualifier("requestMappingHandlerMapping") RequestMappingHandlerMapping handlerMapping) { + return new FastMvcMappingRegister(handlerMapping); } @@ -32,8 +33,8 @@ public EntityManagerInitializer entityManagerInitializer(EntityManager entityMan @Bean - public ScriptMappingRegister scriptMappingRegister(MvcMappingRegister mvcMappingRegister) { - return new ScriptMappingRegister(mvcMappingRegister); + public FastScriptMappingRegister scriptMappingRegister(FastMvcMappingRegister fastMvcMappingRegister) { + return new FastScriptMappingRegister(fastMvcMappingRegister); } } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/MvcMappingRegister.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/FastMvcMappingRegister.java similarity index 98% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/MvcMappingRegister.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/FastMvcMappingRegister.java index dfe3ed39..35d95f1e 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/MvcMappingRegister.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/mapping/FastMvcMappingRegister.java @@ -10,7 +10,7 @@ import java.lang.reflect.Method; @AllArgsConstructor -public class MvcMappingRegister { +public class FastMvcMappingRegister { private final RequestMappingHandlerMapping handlerMapping; diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMappingRegister.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/FastScriptMappingRegister.java similarity index 85% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMappingRegister.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/FastScriptMappingRegister.java index a94e9134..9dc8583f 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptMappingRegister.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/FastScriptMappingRegister.java @@ -1,13 +1,13 @@ package com.codingapi.springboot.fast.script; -import com.codingapi.springboot.fast.mapping.MvcMappingRegister; +import com.codingapi.springboot.fast.mapping.FastMvcMappingRegister; import com.codingapi.springboot.framework.dto.response.Response; import lombok.AllArgsConstructor; @AllArgsConstructor -public class ScriptMappingRegister { +public class FastScriptMappingRegister { - private final MvcMappingRegister mappingRegister; + private final FastMvcMappingRegister mappingRegister; /** * test dynamic mapping diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 4912e175..2e34431d 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.2 + 2.8.3 springboot-starter-security diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java index 27c81da9..339ae029 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java @@ -3,6 +3,7 @@ import com.codingapi.springboot.security.configurer.HttpSecurityConfigurer; import com.codingapi.springboot.security.controller.VersionController; import com.codingapi.springboot.security.dto.request.LoginRequest; +import com.codingapi.springboot.security.dto.response.LoginResponse; import com.codingapi.springboot.security.filter.*; import com.codingapi.springboot.security.gateway.Token; import com.codingapi.springboot.security.gateway.TokenGateway; @@ -61,7 +62,7 @@ public PasswordEncoder passwordEncoder() { @Bean @ConditionalOnMissingBean public AuthenticationTokenFilter authenticationTokenFilter() { - return (request, response, chain) -> { + return (request, response) -> { }; } @@ -77,8 +78,12 @@ public void preHandle(HttpServletRequest request, HttpServletResponse response, } @Override - public void postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest handler, Token token) { - + public LoginResponse postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest loginRequest, Token token) { + LoginResponse loginResponse = new LoginResponse(); + loginResponse.setUsername(token.getUsername()); + loginResponse.setToken(token.getToken()); + loginResponse.setAuthorities(token.getAuthorities()); + return loginResponse; } }; } diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/dto/response/LoginResponse.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/dto/response/LoginResponse.java index cdfc3a3f..d717d36e 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/dto/response/LoginResponse.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/dto/response/LoginResponse.java @@ -12,5 +12,6 @@ public class LoginResponse { private String username; private String token; private List authorities; + private Object data; } diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java index 4e094e71..020ea664 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java @@ -1,12 +1,13 @@ package com.codingapi.springboot.security.filter; -import javax.servlet.FilterChain; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; public interface AuthenticationTokenFilter { - void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain); + void doFilter(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException; } diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java index 1b7286cf..ed73501b 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java @@ -66,7 +66,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse } SecurityContextHolder.getContext().setAuthentication(token.getAuthenticationToken()); - authenticationTokenFilter.doFilter(request, response, chain); + authenticationTokenFilter.doFilter(request, response); } } chain.doFilter(request, response); diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java index 2bf4ab52..4f2939be 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java @@ -76,16 +76,11 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()), TokenContext.getExtra()); - LoginResponse login = new LoginResponse(); - login.setUsername(user.getUsername()); - login.setToken(token.getToken()); - login.setAuthorities(token.getAuthorities()); + LoginResponse loginResponse = loginHandler.postHandle(request, response, loginRequest, token); - String content = JSONObject.toJSONString(SingleResponse.of(login)); + String content = JSONObject.toJSONString(SingleResponse.of(loginResponse)); IOUtils.write(content, response.getOutputStream(), StandardCharsets.UTF_8); - loginHandler.postHandle(request, response, loginRequest, token); - LoginRequestContext.getInstance().clean(); } diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java index 97de8972..ed0b5876 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java @@ -1,6 +1,7 @@ package com.codingapi.springboot.security.filter; import com.codingapi.springboot.security.dto.request.LoginRequest; +import com.codingapi.springboot.security.dto.response.LoginResponse; import com.codingapi.springboot.security.gateway.Token; import javax.servlet.http.HttpServletRequest; @@ -9,7 +10,7 @@ public interface SecurityLoginHandler { - void preHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest handler) throws Exception; + void preHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest loginRequest) throws Exception; - void postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest handler, Token token); + LoginResponse postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest loginRequest, Token token); } diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 911d6cc0..e168fb42 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.2 + 2.8.3 springboot-starter From a0db5272bfa6e4b8a15b4ad0ccae0bafa5fc442d Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 12 Jul 2024 10:52:47 +0800 Subject: [PATCH 044/129] #48 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/dto/request/Filter.java | 2 +- .../framework/dto/request/SearchRequest.java | 10 ++++++---- .../framework/rest/RestClientTest.java | 18 +++++++++++++----- 7 files changed, 24 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index 4f2e3de7..64f738cd 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.3 + 2.8.4 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index b366a0b8..a2a0edf9 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.3 + 2.8.4 4.0.0 diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 2e34431d..18424120 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.3 + 2.8.4 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index e168fb42..4b79616a 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.3 + 2.8.4 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java index 55c901b8..db6c5477 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java @@ -25,7 +25,7 @@ public Filter(String key, Object... value) { } public Filter(String key, Filter... value) { - this(key, null, value); + this(key, null, value); } public static Filter as(String key, Relation relation, Object... value) { diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java index c6bc6f60..b8fc5ae9 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java @@ -16,6 +16,7 @@ import java.util.Base64; import java.util.Enumeration; import java.util.List; +import java.util.stream.Collectors; /** * HttpServletRequest 请求参数解析成 PageRequest对象 @@ -211,15 +212,17 @@ public PageRequest toPageRequest(Class clazz) { for (String key : jsonObject.keySet()) { JSONArray value = jsonObject.getJSONArray(key); if (value != null && !value.isEmpty()) { - List values = value.stream().map(Object::toString).toList(); + List values = value.stream().map(Object::toString).collect(Collectors.toList()); content.addFilter(key, values); } } } } + Enumeration enumeration = request.getParameterNames(); - request.getParameterNames().asIterator().forEachRemaining(key -> { + while (enumeration.hasMoreElements()){ + String key = enumeration.nextElement(); if (!removeKeys.contains(key)) { String value = request.getParameter(key); if (StringUtils.hasLength(value)) { @@ -238,8 +241,7 @@ public PageRequest toPageRequest(Class clazz) { } } } - }); - + } return pageRequest; } diff --git a/springboot-starter/src/test/java/com/codingapi/springboot/framework/rest/RestClientTest.java b/springboot-starter/src/test/java/com/codingapi/springboot/framework/rest/RestClientTest.java index c6a48d79..94a3d3ff 100644 --- a/springboot-starter/src/test/java/com/codingapi/springboot/framework/rest/RestClientTest.java +++ b/springboot-starter/src/test/java/com/codingapi/springboot/framework/rest/RestClientTest.java @@ -5,6 +5,7 @@ import com.codingapi.springboot.framework.rest.properties.HttpProxyProperties; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; +import org.springframework.http.HttpHeaders; import java.net.Proxy; @@ -21,14 +22,21 @@ void okxTest() { proxyProperties.setProxyType(Proxy.Type.HTTP); proxyProperties.setProxyHost("127.0.0.1"); proxyProperties.setProxyPort(7890); + + HttpHeaders headers = new HttpHeaders(); + headers.set("x-simulated-trading","1"); + headers.set("User-Agent", "Application"); RestClient restClient = new RestClient(proxyProperties,baseUrl,5,"{}",null,null); - String response = restClient.get("api/v5/market/candles", RestParam.create() - .add("instId","BTC-USDT") - .add("bar","1m") - .add("limit","300") + String response = restClient.get( + "api/v5/market/candles", + headers, + RestParam.create() + .add("instId","BTC-USDT") + .add("bar","1m") + .add("limit","300") ); log.info("response:{}",response); JSONObject jsonObject = JSONObject.parseObject(response); assertEquals(jsonObject.getJSONArray("data").size(),300); } -} \ No newline at end of file +} From 04b76dc29e65695f2df8acb2fc938ccd8de10115 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 7 Aug 2024 21:38:39 +0800 Subject: [PATCH 045/129] #49 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../springboot/fast/jdbc/JdbcQuery.java | 11 +++- .../fast/jpa/repository/BaseRepository.java | 16 ++++++ .../repository/DynamicNativeRepository.java | 50 +++++++++++++++++++ .../jpa/repository/DynamicRepository.java | 9 +--- .../fast/jpa/repository/FastRepository.java | 18 ++----- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 9 files changed, 86 insertions(+), 26 deletions(-) create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/BaseRepository.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java diff --git a/pom.xml b/pom.xml index 64f738cd..acaafde1 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.4 + 2.8.5 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index a2a0edf9..c810d8e4 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.4 + 2.8.5 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java index 423ba1ea..d20e379c 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java @@ -51,13 +51,22 @@ public Page queryForPage(String sql, String countSql, Class clazz, Pag return new PageImpl<>(list, pageRequest, count); } + public Page queryForPage(String sql, Class clazz, PageRequest pageRequest, Object... params) { + String countSql = "select count(1) "+sql; + return this.queryForPage(sql, countSql, clazz, pageRequest, params); + } + public Page> queryForPage(String sql, String countSql, PageRequest pageRequest, Object... params) { List> list = jdbcTemplate.query(sql, params, new CamelCaseRowMapper()); - long count = this.countQuery(countSql, params); return new PageImpl<>(list, pageRequest, count); } + public Page> queryForPage(String sql, PageRequest pageRequest, Object... params) { + String countSql = "select count(1) "+sql; + return this.queryForPage(sql, countSql, pageRequest, params); + } + private long countQuery(String sql, Object... params) { int paramsLength = params.length; diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/BaseRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/BaseRepository.java new file mode 100644 index 00000000..b4200b97 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/BaseRepository.java @@ -0,0 +1,16 @@ +package com.codingapi.springboot.fast.jpa.repository; + +import org.springframework.core.ResolvableType; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.NoRepositoryBean; + +@NoRepositoryBean +public interface BaseRepository extends JpaRepository { + + @SuppressWarnings("unchecked") + default Class getEntityClass() { + ResolvableType resolvableType = ResolvableType.forClass(getClass()).as(BaseRepository.class); + return (Class) resolvableType.getGeneric(0).resolve(); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java new file mode 100644 index 00000000..1dd846b9 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java @@ -0,0 +1,50 @@ +package com.codingapi.springboot.fast.jpa.repository; + +import com.codingapi.springboot.fast.jdbc.JdbcQueryContext; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.repository.NoRepositoryBean; + +import java.util.List; +import java.util.Map; + +@NoRepositoryBean +public interface DynamicNativeRepository extends BaseRepository { + + default List> dynamicNativeListMapQuery(String sql, Object... params) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForList(sql, params); + } + + default List dynamicNativeListQuery(String sql, Object... params) { + return dynamicNativeListQuery(getEntityClass(), sql, params); + } + + default List dynamicNativeListQuery(Class clazz, String sql, Object... params) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForList(sql, clazz, params); + } + + default Page dynamicNativePageQuery(String sql, String countSql, PageRequest request, Object... params) { + return dynamicNativePageQuery(getEntityClass(), sql, countSql, request, params); + } + + default Page dynamicNativePageQuery(String sql, PageRequest request, Object... params) { + return dynamicNativePageQuery(getEntityClass(), sql, request, params); + } + + default Page dynamicNativePageQuery(Class clazz, String sql, String countSql, PageRequest request, Object... params) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForPage(sql, countSql, clazz, request, params); + } + + default Page dynamicNativePageQuery(Class clazz, String sql, PageRequest request, Object... params) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForPage(sql, clazz, request, params); + } + + default Page> dynamicNativePageMapQuery(String sql, String countSql, PageRequest request, Object... params) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForPage(sql, countSql, request, params); + } + + default Page> dynamicNativePageMapQuery(String sql, PageRequest request, Object... params) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForPage(sql, request, params); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java index 992f8ab2..b8e0850c 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java @@ -1,22 +1,15 @@ package com.codingapi.springboot.fast.jpa.repository; import com.codingapi.springboot.fast.jpa.JpaQueryContext; -import org.springframework.core.ResolvableType; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.repository.NoRepositoryBean; import java.util.List; @NoRepositoryBean @SuppressWarnings("unchecked") -public interface DynamicRepository extends JpaRepository { - - default Class getEntityClass() { - ResolvableType resolvableType = ResolvableType.forClass(this.getClass()).as(DynamicRepository.class); - return resolvableType.getGeneric(new int[]{0}).resolve(); - } +public interface DynamicRepository extends BaseRepository { default List dynamicListQuery(String sql, Object... params) { return (List) JpaQueryContext.getInstance().getJPAQuery().listQuery(getEntityClass(), sql, params); diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java index d3e2deb8..1cc0c6c0 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java @@ -2,7 +2,6 @@ import com.codingapi.springboot.framework.dto.request.PageRequest; import com.codingapi.springboot.framework.dto.request.SearchRequest; -import org.springframework.core.ResolvableType; import org.springframework.data.domain.Page; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; @@ -10,32 +9,25 @@ /** * 更强大的Repository对象 + * * @param * @param */ @NoRepositoryBean -public interface FastRepository extends JpaRepository, JpaSpecificationExecutor, DynamicRepository { +public interface FastRepository extends JpaRepository, JpaSpecificationExecutor, DynamicRepository, DynamicNativeRepository { default Page findAll(PageRequest request) { if (request.hasFilter()) { - Class clazz = getDomainClass(); + Class clazz = getEntityClass(); ExampleBuilder exampleBuilder = new ExampleBuilder(request, clazz); return findAll(exampleBuilder.getExample(), request); } return findAll((org.springframework.data.domain.PageRequest) request); } - - @SuppressWarnings("unchecked") - default Class getDomainClass() { - ResolvableType resolvableType = ResolvableType.forClass(getClass()).as(FastRepository.class); - return (Class) resolvableType.getGeneric(0).resolve(); - } - - default Page pageRequest(PageRequest request) { if (request.hasFilter()) { - Class clazz = getDomainClass(); + Class clazz = getEntityClass(); DynamicSQLBuilder dynamicSQLBuilder = new DynamicSQLBuilder(request, clazz); return dynamicPageQuery(dynamicSQLBuilder.getHQL(), request, dynamicSQLBuilder.getParams()); } @@ -44,7 +36,7 @@ default Page pageRequest(PageRequest request) { default Page searchRequest(SearchRequest request) { - Class clazz = getDomainClass(); + Class clazz = getEntityClass(); return pageRequest(request.toPageRequest(clazz)); } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 18424120..3cd99f08 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.4 + 2.8.5 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 4b79616a..d85057b3 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.4 + 2.8.5 springboot-starter From c48c61cf6ae110dcbdb3d409bd7e8c3b1388948d Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 7 Sep 2024 10:02:30 +0800 Subject: [PATCH 046/129] add ClassLoaderUtils.java --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/utils/ClassLoaderUtils.java | 99 +++++++++++++++++++ 5 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/ClassLoaderUtils.java diff --git a/pom.xml b/pom.xml index acaafde1..e37ad7a4 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.5 + 2.8.6 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index c810d8e4..92f0e78a 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.5 + 2.8.6 4.0.0 diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 3cd99f08..044edc39 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.5 + 2.8.6 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index d85057b3..59fa2065 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.5 + 2.8.6 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/ClassLoaderUtils.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/ClassLoaderUtils.java new file mode 100644 index 00000000..df9cd18b --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/ClassLoaderUtils.java @@ -0,0 +1,99 @@ +package com.codingapi.springboot.framework.utils; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +public class ClassLoaderUtils { + + public static URLClassLoader createClassLoader(String jarPath) throws MalformedURLException { + File file = new File(jarPath); + if(!file.exists()){ + throw new RuntimeException("jar file not found:"+jarPath); + } + URL[] urls = new URL[]{file.toURI().toURL()}; + return new URLClassLoader(urls, ClassLoader.getSystemClassLoader()); + } + + public static List findAllClasses(URLClassLoader classLoader) throws URISyntaxException, IOException { + List classNames = new ArrayList<>(); + URL[] urls = classLoader.getURLs(); + for (URL url : urls) { + if (url.getProtocol().equals("file")) { + File file = new File(url.toURI()); + if (file.isDirectory()) { + classNames.addAll(findClassesInDirectory(file, "")); + } else if (file.getName().endsWith(".jar")) { + classNames.addAll(findClassesInJar(new JarFile(file))); + } + } + } + return classNames; + } + + public static List> findJarClasses(String jarPath) throws IOException, URISyntaxException { + URLClassLoader classLoader = createClassLoader(jarPath); + List classList = ClassLoaderUtils.findAllClasses(classLoader); + List> classes = new ArrayList<>(); + for(String className:classList){ + try { + Class driverClass = classLoader.loadClass(className); + classes.add(driverClass); + }catch (NoClassDefFoundError | ClassNotFoundException ignored){} + } + return classes; + } + + public static List> findJarClass(String jarPath,Class clazz) throws IOException, URISyntaxException { + URLClassLoader classLoader = createClassLoader(jarPath); + List classList = ClassLoaderUtils.findAllClasses(classLoader); + List> classes = new ArrayList<>(); + for(String className:classList){ + try { + Class driverClass = classLoader.loadClass(className); + if(clazz.isAssignableFrom(driverClass)){ + classes.add(driverClass); + } + }catch (NoClassDefFoundError | ClassNotFoundException ignored){} + } + return classes; + } + + private static List findClassesInDirectory(File directory, String packageName) { + List classNames = new ArrayList<>(); + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + classNames.addAll(findClassesInDirectory(file, packageName + file.getName() + ".")); + } else if (file.getName().endsWith(".class")) { + String className = packageName + file.getName().replace(".class", ""); + classNames.add(className); + } + } + } + return classNames; + } + + private static List findClassesInJar(JarFile jarFile) { + List classNames = new ArrayList<>(); + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String name = entry.getName(); + if (name.endsWith(".class")) { + String className = name.replace('/', '.').replace(".class", ""); + classNames.add(className); + } + } + return classNames; + } +} From ba5fdbdfc985619516c356fcaba4d5e7f98f2e03 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 21 Sep 2024 18:38:13 +0800 Subject: [PATCH 047/129] #50 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/dto/request/PageRequest.java | 66 ++++--------------- 5 files changed, 17 insertions(+), 57 deletions(-) diff --git a/pom.xml b/pom.xml index e37ad7a4..9eb6033d 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.6 + 2.8.7 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 92f0e78a..cc37892f 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.6 + 2.8.7 4.0.0 diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 044edc39..5d5a415c 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.6 + 2.8.7 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 59fa2065..b45f6506 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.6 + 2.8.7 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java index ff5b3df5..cf62e20e 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/PageRequest.java @@ -2,11 +2,8 @@ import lombok.Getter; import lombok.Setter; -import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import java.util.Optional; - public class PageRequest extends org.springframework.data.domain.PageRequest { @Getter @@ -14,20 +11,20 @@ public class PageRequest extends org.springframework.data.domain.PageRequest { private int current; @Setter - @Getter private int pageSize; @Getter - private final RequestFilter requestFilter = new RequestFilter(); + private Sort sort; + @Getter + private final RequestFilter requestFilter = new RequestFilter(); - private org.springframework.data.domain.PageRequest pageRequest; public PageRequest(int current, int pageSize, Sort sort) { super(current, pageSize, sort); this.current = current; this.pageSize = pageSize; - this.pageRequest = org.springframework.data.domain.PageRequest.of(current, pageSize, sort); + this.sort = sort; } @@ -39,6 +36,7 @@ public String getStringFilter(String key) { return requestFilter.getStringFilter(key); } + public String getStringFilter(String key, String defaultValue) { return requestFilter.getStringFilter(key, defaultValue); } @@ -47,33 +45,20 @@ public int getIntFilter(String key) { return requestFilter.getIntFilter(key); } + public int getIntFilter(String key, int defaultValue) { return requestFilter.getIntFilter(key, defaultValue); } + public boolean hasFilter() { return requestFilter.hasFilter(); } @Override - public Sort getSort() { - return pageRequest.getSort(); - } - - @Override - public PageRequest next() { - return new PageRequest(current + 1, getPageSize(), getSort()); - } - - @Override - public PageRequest previous() { - return current == 0 ? this : new PageRequest(current - 1, getPageSize(), getSort()); - } - - @Override - public PageRequest first() { - return new PageRequest(0, getPageSize(), getSort()); + public int getPageSize() { + return pageSize; } @Override @@ -91,37 +76,12 @@ public boolean hasPrevious() { return current > 0; } - @Override - public Pageable previousOrFirst() { - return pageRequest.previousOrFirst(); - } - - @Override - public boolean isPaged() { - return pageRequest.isPaged(); - } - - @Override - public boolean isUnpaged() { - return pageRequest.isUnpaged(); - } - - @Override - public Sort getSortOr(Sort sort) { - return pageRequest.getSortOr(sort); - } - - @Override - public Optional toOptional() { - return pageRequest.toOptional(); - } - public void addSort(Sort sort) { - Sort nowSort = pageRequest.getSort(); + Sort nowSort = this.sort; if (nowSort == Sort.unsorted()) { - this.pageRequest = new PageRequest(getCurrent(), getPageSize(), sort); + this.sort = sort; } else { - pageRequest.getSort().and(sort); + this.sort.and(sort); } } @@ -156,4 +116,4 @@ public static PageRequest of(int page, int size) { public static PageRequest of(int page, int size, Sort sort) { return new PageRequest(page, size, sort); } -} \ No newline at end of file +} From d0bb08a8794340504a1706aa1b218a911d9a7e75 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 26 Sep 2024 16:53:11 +0800 Subject: [PATCH 048/129] update 0.8.12 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9eb6033d..3724575f 100644 --- a/pom.xml +++ b/pom.xml @@ -269,7 +269,7 @@ org.jacoco jacoco-maven-plugin - 0.8.9 + 0.8.12 From 602ad595c5ad1424476d390dabab83f3a9a8f7fa Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 28 Oct 2024 09:01:19 +0800 Subject: [PATCH 049/129] update 2.8.8 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../jpa/repository/DynamicSQLBuilder.java | 12 ++++++++- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/dto/request/Filter.java | 10 ++++++++ .../framework/dto/request/Relation.java | 2 ++ .../framework/dto/request/SearchRequest.java | 25 +++++++++++++++---- 8 files changed, 47 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index 3724575f..399ade2d 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.7 + 2.8.8 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index cc37892f..24a2af7b 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.7 + 2.8.8 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java index 06705ad8..caa1a9d7 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java @@ -103,6 +103,16 @@ private void buildSQL(Filter filter, StringBuilder hql) { params.add("%" + filter.getValue()[0] + "%"); paramIndex++; } + if (filter.isLeftLike()) { + hql.append(filter.getKey()).append(" LIKE ?").append(paramIndex); + params.add("%" + filter.getValue()[0]); + paramIndex++; + } + if (filter.isRightLike()) { + hql.append(filter.getKey()).append(" LIKE ?").append(paramIndex); + params.add(filter.getValue()[0] + "%"); + paramIndex++; + } if (filter.isIn()) { hql.append(filter.getKey()).append(" IN (").append("?").append(paramIndex).append(")"); params.add(Arrays.asList(filter.getValue())); @@ -140,4 +150,4 @@ private void buildSQL(Filter filter, StringBuilder hql) { public Object[] getParams() { return params.toArray(); } -} \ No newline at end of file +} diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 5d5a415c..e85fb3b3 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.7 + 2.8.8 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index b45f6506..84ab4cc5 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.7 + 2.8.8 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java index db6c5477..723448d5 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java @@ -52,6 +52,16 @@ public boolean isLike() { return relation == Relation.LIKE; } + + public boolean isLeftLike() { + return relation == Relation.LEFT_LIKE; + } + + public boolean isRightLike() { + return relation == Relation.RIGHT_LIKE; + } + + public boolean isBetween() { return relation == Relation.BETWEEN; } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java index a5b3eaa0..7941a3c4 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java @@ -4,6 +4,8 @@ public enum Relation { EQUAL, LIKE, + LEFT_LIKE, + RIGHT_LIKE, BETWEEN, IN, GREATER_THAN, diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java index b8fc5ae9..f559812b 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java @@ -137,19 +137,34 @@ public void addFilter(String key, List value) { } + private Class getKeyType(String key) { String[] keys = key.split("\\."); Class keyClass = clazz; + for (String k : keys) { - Field[] fields = keyClass.getDeclaredFields(); + keyClass = findFieldInHierarchy(keyClass, k); + + if (keyClass == null) { + throw new IllegalArgumentException("Field " + k + " not found in class hierarchy."); + } + } + return keyClass; + } + + private Class findFieldInHierarchy(Class clazz, String fieldName) { + Class currentClass = clazz; + + while (currentClass != null) { + Field[] fields = currentClass.getDeclaredFields(); for (Field field : fields) { - if (field.getName().equals(k)) { - keyClass = field.getType(); - break; + if (field.getName().equals(fieldName)) { + return field.getType(); } } + currentClass = currentClass.getSuperclass(); // 向上查找父类 } - return keyClass; + return null; } } From 555385185756af475c73beb7f71a2973a8974efe Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 7 Nov 2024 12:02:37 +0800 Subject: [PATCH 050/129] fix event bug --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../handler/ApplicationHandlerUtils.java | 38 ++++++------------- .../framework/handler/IHandler.java | 14 ++++++- 6 files changed, 27 insertions(+), 33 deletions(-) diff --git a/pom.xml b/pom.xml index 399ade2d..6982e4d3 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.8 + 2.8.9 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 24a2af7b..1ba56b09 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.8 + 2.8.9 4.0.0 diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index e85fb3b3..d4216971 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.8 + 2.8.9 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 84ab4cc5..cb6be28d 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.8 + 2.8.9 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/ApplicationHandlerUtils.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/ApplicationHandlerUtils.java index 7817ae56..a64c8fcc 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/ApplicationHandlerUtils.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/ApplicationHandlerUtils.java @@ -1,18 +1,14 @@ package com.codingapi.springboot.framework.handler; import com.codingapi.springboot.framework.event.IEvent; -import lombok.extern.slf4j.Slf4j; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; -@Slf4j class ApplicationHandlerUtils implements IHandler { private static ApplicationHandlerUtils instance; - private List> handlers; + private final List> handlers; private ApplicationHandlerUtils() { @@ -47,39 +43,27 @@ public void addHandler(IHandler handler) { @Override public void handler(IEvent event) { for (IHandler handler : handlers) { - String targetClassName = null; try { Class eventClass = event.getClass(); - Class targetClass = getHandlerEventClass(handler); + Class targetClass = handler.getHandlerEventClass(); if (eventClass.equals(targetClass)) { - targetClassName = targetClass.getName(); handler.handler(event); } } catch (Exception e) { - //IPersistenceEvent 抛出异常 - if ("com.codingapi.springboot.framework.persistence.PersistenceEvent".equals(targetClassName)) { - throw e; + Exception error = null; + try { + handler.error(e); + } catch (Exception err) { + error = err; } - log.warn("handler exception", e); - handler.error(e); - - } - } - } - - private Class getHandlerEventClass(IHandler handler) { - Type[] types = handler.getClass().getGenericInterfaces(); - for (Type type : types) { - if (type instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) type; - Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); - if (actualTypeArguments != null) { - return (Class) actualTypeArguments[0]; + if (error != null) { + throw new RuntimeException(error); } } } - return null; } + + } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/IHandler.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/IHandler.java index 45db5dd7..21cdecd8 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/IHandler.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/IHandler.java @@ -1,6 +1,7 @@ package com.codingapi.springboot.framework.handler; import com.codingapi.springboot.framework.event.IEvent; +import org.springframework.core.ResolvableType; /** * handler 订阅 @@ -21,9 +22,18 @@ public interface IHandler { * * @param exception 异常信息 */ - default void error(Exception exception) { + default void error(Exception exception) throws Exception{ + throw exception; + } + + + /** + * 获取订阅的事件类型 + */ + default Class getHandlerEventClass() { + ResolvableType resolvableType = ResolvableType.forClass(getClass()).as(IHandler.class); + return (Class) resolvableType.getGeneric(0).resolve(); } - ; } From cb501d582831d2999c30410ff8c2da94c86aba6e Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 7 Nov 2024 14:14:53 +0800 Subject: [PATCH 051/129] fix event bug --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 6982e4d3..b9e5aaf0 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.9 + 2.8.10 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 1ba56b09..4c095838 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.9 + 2.8.10 4.0.0 diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index d4216971..665982f1 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.9 + 2.8.10 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index cb6be28d..21915339 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.9 + 2.8.10 springboot-starter From b825aff2ac57498329b6d61893e40fc83fd1a9be Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 9 Nov 2024 09:16:47 +0800 Subject: [PATCH 052/129] fix event bug --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../ApplicationHandlerUtils.java | 25 +++--- .../framework/event/DomainEvent.java | 8 +- .../framework/event/DomainEventContext.java | 4 +- .../framework/event/EventStackContext.java | 80 ++++++++++++++++++ .../framework/event/EventTraceContext.java | 81 +++++++++++++++++++ .../framework/{handler => event}/Handler.java | 2 +- .../HandlerBeanDefinitionRegistrar.java | 2 +- .../springboot/framework/event/IEvent.java | 4 +- .../{handler => event}/IHandler.java | 8 +- .../SpringEventHandler.java | 19 ++++- .../SpringHandlerConfiguration.java | 2 +- .../framework/exception/EventException.java | 17 ++++ .../exception/EventLoopException.java | 17 ++++ .../framework/utils/RandomGenerator.java | 22 +++++ .../main/resources/META-INF/spring.factories | 6 +- ...ot.autoconfigure.AutoConfiguration.imports | 6 +- .../handler/DemoChangeLogHandler.java | 2 + .../framework/handler/DemoCreateHandler.java | 2 + .../framework/handler/DemoDeleteHandler.java | 2 + .../handler/DemoPersistEventHandler.java | 4 +- .../handler/EntityFiledChangeHandler.java | 4 +- 25 files changed, 288 insertions(+), 37 deletions(-) rename springboot-starter/src/main/java/com/codingapi/springboot/framework/{handler => event}/ApplicationHandlerUtils.java (69%) create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventStackContext.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventTraceContext.java rename springboot-starter/src/main/java/com/codingapi/springboot/framework/{handler => event}/Handler.java (76%) rename springboot-starter/src/main/java/com/codingapi/springboot/framework/{handler => event}/HandlerBeanDefinitionRegistrar.java (96%) rename springboot-starter/src/main/java/com/codingapi/springboot/framework/{handler => event}/IHandler.java (73%) rename springboot-starter/src/main/java/com/codingapi/springboot/framework/{handler => event}/SpringEventHandler.java (64%) rename springboot-starter/src/main/java/com/codingapi/springboot/framework/{handler => event}/SpringHandlerConfiguration.java (89%) create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventLoopException.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/RandomGenerator.java diff --git a/pom.xml b/pom.xml index b9e5aaf0..f93e9daf 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.10 + 2.8.11 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 4c095838..a2fc1cdf 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.10 + 2.8.11 4.0.0 diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 665982f1..11b91dab 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.10 + 2.8.11 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 21915339..ca03cc75 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.10 + 2.8.11 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/ApplicationHandlerUtils.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/ApplicationHandlerUtils.java similarity index 69% rename from springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/ApplicationHandlerUtils.java rename to springboot-starter/src/main/java/com/codingapi/springboot/framework/event/ApplicationHandlerUtils.java index a64c8fcc..0e97bc4a 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/ApplicationHandlerUtils.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/ApplicationHandlerUtils.java @@ -1,6 +1,7 @@ -package com.codingapi.springboot.framework.handler; +package com.codingapi.springboot.framework.event; -import com.codingapi.springboot.framework.event.IEvent; +import com.codingapi.springboot.framework.exception.EventException; +import com.codingapi.springboot.framework.exception.EventLoopException; import java.util.ArrayList; import java.util.List; @@ -42,28 +43,32 @@ public void addHandler(IHandler handler) { @Override public void handler(IEvent event) { + Class eventClass = event.getClass(); + List errorStack = new ArrayList<>(); + boolean throwException = false; for (IHandler handler : handlers) { try { - Class eventClass = event.getClass(); Class targetClass = handler.getHandlerEventClass(); if (eventClass.equals(targetClass)) { handler.handler(event); } } catch (Exception e) { - Exception error = null; + if (e instanceof EventLoopException) { + throw e; + } try { handler.error(e); + errorStack.add(e); } catch (Exception err) { - error = err; - } - if (error != null) { - throw new RuntimeException(error); + throwException = true; + errorStack.add(err); } } } + if(throwException){ + throw new EventException(errorStack); + } } - - } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEvent.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEvent.java index 1f478ac1..a03d694e 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEvent.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEvent.java @@ -18,10 +18,14 @@ public class DomainEvent extends ApplicationEvent { @Getter private final boolean sync; - public DomainEvent(Object source, boolean sync) { + @Getter + private final String traceId; + + + public DomainEvent(Object source, boolean sync, String traceId) { super(source); this.event = (IEvent) source; this.sync = sync; + this.traceId = traceId; } - } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEventContext.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEventContext.java index f7bcd7c2..a22799e2 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEventContext.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEventContext.java @@ -25,7 +25,9 @@ public static DomainEventContext getInstance() { private void push(IEvent event, boolean sync) { if (context != null) { - context.publishEvent(new DomainEvent(event, sync)); + String traceId = EventTraceContext.getInstance().getOrCreateTrace(); + EventTraceContext.getInstance().addEvent(traceId,event); + context.publishEvent(new DomainEvent(event, sync,traceId)); } } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventStackContext.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventStackContext.java new file mode 100644 index 00000000..bcc01407 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventStackContext.java @@ -0,0 +1,80 @@ +package com.codingapi.springboot.framework.event; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 事件栈上下文 + */ +public class EventStackContext { + + private final Map>> eventClassStack = new HashMap<>(); + private final Map> eventStack = new HashMap<>(); + + @Getter + private final static EventStackContext instance = new EventStackContext(); + + private EventStackContext() { + + } + + private void addEventClass(String traceId, IEvent event) { + List> events = eventClassStack.get(traceId); + if (events == null) { + events = new ArrayList<>(); + } + events.add(event.getClass()); + eventClassStack.put(traceId, events); + } + + private void addEventStack(String traceId, IEvent event) { + List events = eventStack.get(traceId); + if (events == null) { + events = new ArrayList<>(); + } + events.add(event); + eventStack.put(traceId, events); + } + + + void addEvent(String traceId, IEvent event) { + addEventClass(traceId, event); + addEventStack(traceId, event); + } + + boolean checkEventLoop(String traceId, IEvent event) { + List> events = eventClassStack.get(traceId); + if (events != null) { + return events.contains(event.getClass()); + } + return false; + } + + public List getEvents(String eventKey) { + if(eventKey!=null) { + String traceId = eventKey.split("#")[0]; + return eventStack.get(traceId); + } + return null; + } + + public List> getEventClasses(String eventKey) { + if(eventKey!=null) { + String traceId = eventKey.split("#")[0]; + return eventClassStack.get(traceId); + } + return null; + } + + + void remove(String traceId) { + eventStack.remove(traceId); + eventClassStack.remove(traceId); + } + + +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventTraceContext.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventTraceContext.java new file mode 100644 index 00000000..844d2cf9 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventTraceContext.java @@ -0,0 +1,81 @@ +package com.codingapi.springboot.framework.event; + +import com.codingapi.springboot.framework.exception.EventLoopException; +import com.codingapi.springboot.framework.utils.RandomGenerator; +import lombok.Getter; + +import java.util.*; + +/** + * 事件跟踪上下文 + */ +public class EventTraceContext { + + @Getter + private final static EventTraceContext instance = new EventTraceContext(); + + // trace key + private final Set traceKeys = new HashSet<>(); + + // thread local + private final ThreadLocal threadLocal = new ThreadLocal<>(); + + // event listenerKey state + private final Map eventKeyState = new HashMap<>(); + + + private EventTraceContext() { + } + + String getOrCreateTrace() { + String eventKey = threadLocal.get(); + if (eventKey != null) { + return eventKey.split("#")[0]; + } + String traceId = UUID.randomUUID().toString().replaceAll("-", ""); + traceKeys.add(traceId); + return traceId; + } + + /** + * get event key + * traceId = eventKey.split("#")[0] + */ + public String getEventKey() { + return threadLocal.get(); + } + + void createEventKey(String traceId) { + String eventKey = traceId + "#" + RandomGenerator.randomString(8); + eventKeyState.put(eventKey, false); + threadLocal.set(eventKey); + } + + void checkEventState() { + String eventKey = threadLocal.get(); + if (eventKey != null) { + boolean state = eventKeyState.get(eventKey); + if (!state) { + // event execute finish + String traceId = eventKey.split("#")[0]; + traceKeys.remove(traceId); + EventStackContext.getInstance().remove(traceId); + } + eventKeyState.remove(eventKey); + } + threadLocal.remove(); + } + + void addEvent(String traceId, IEvent event) { + boolean hasEventLoop = EventStackContext.getInstance().checkEventLoop(traceId, event); + if (hasEventLoop) { + List> stack = EventStackContext.getInstance().getEventClasses(traceId); + traceKeys.remove(traceId); + EventStackContext.getInstance().remove(traceId); + eventKeyState.remove(traceId); + threadLocal.remove(); + throw new EventLoopException(stack, event); + } + EventStackContext.getInstance().addEvent(traceId, event); + } +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/Handler.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/Handler.java similarity index 76% rename from springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/Handler.java rename to springboot-starter/src/main/java/com/codingapi/springboot/framework/event/Handler.java index d4321a03..6dda24a0 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/Handler.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/Handler.java @@ -1,4 +1,4 @@ -package com.codingapi.springboot.framework.handler; +package com.codingapi.springboot.framework.event; import java.lang.annotation.*; diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/HandlerBeanDefinitionRegistrar.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/HandlerBeanDefinitionRegistrar.java similarity index 96% rename from springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/HandlerBeanDefinitionRegistrar.java rename to springboot-starter/src/main/java/com/codingapi/springboot/framework/event/HandlerBeanDefinitionRegistrar.java index 3f1a76b3..de878c8b 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/HandlerBeanDefinitionRegistrar.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/HandlerBeanDefinitionRegistrar.java @@ -1,4 +1,4 @@ -package com.codingapi.springboot.framework.handler; +package com.codingapi.springboot.framework.event; import com.codingapi.springboot.framework.registrar.RegisterBeanScanner; import lombok.SneakyThrows; diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IEvent.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IEvent.java index ca03ea12..327ca279 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IEvent.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IEvent.java @@ -1,6 +1,8 @@ package com.codingapi.springboot.framework.event; +import java.io.Serializable; + /** * 默认同步事件 *

@@ -8,7 +10,7 @@ * 事件本身不应该同步主业务的事务,即事件对于主业务来说,可成功可失败,成功与失败都不应该强关联主体业务。 * 若需要让主体业务与分支做事务同步的时候,那不应该采用事件机制,而应该直接采用调用的方式实现业务绑定。 */ -public interface IEvent { +public interface IEvent extends Serializable { } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/IHandler.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IHandler.java similarity index 73% rename from springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/IHandler.java rename to springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IHandler.java index 21cdecd8..226ee17d 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/IHandler.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IHandler.java @@ -1,6 +1,5 @@ -package com.codingapi.springboot.framework.handler; +package com.codingapi.springboot.framework.event; -import com.codingapi.springboot.framework.event.IEvent; import org.springframework.core.ResolvableType; /** @@ -19,10 +18,11 @@ public interface IHandler { /** * 异常回掉,在多订阅的情况下,为了实现订阅的独立性,将异常的处理放在回掉函数中。 + * 当异常抛出以后,会阻止后续的事件执行 * * @param exception 异常信息 */ - default void error(Exception exception) throws Exception{ + default void error(Exception exception) throws Exception { throw exception; } @@ -32,7 +32,7 @@ default void error(Exception exception) throws Exception{ */ default Class getHandlerEventClass() { ResolvableType resolvableType = ResolvableType.forClass(getClass()).as(IHandler.class); - return (Class) resolvableType.getGeneric(0).resolve(); + return resolvableType.getGeneric(0).resolve(); } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/SpringEventHandler.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/SpringEventHandler.java similarity index 64% rename from springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/SpringEventHandler.java rename to springboot-starter/src/main/java/com/codingapi/springboot/framework/event/SpringEventHandler.java index 9796511b..5ec7b9ba 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/SpringEventHandler.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/SpringEventHandler.java @@ -1,6 +1,5 @@ -package com.codingapi.springboot.framework.handler; +package com.codingapi.springboot.framework.event; -import com.codingapi.springboot.framework.event.DomainEvent; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationListener; @@ -28,11 +27,23 @@ public SpringEventHandler(List handlers) { @Override public void onApplicationEvent(DomainEvent domainEvent) { + String traceId = domainEvent.getTraceId(); + if (domainEvent.isSync()) { - ApplicationHandlerUtils.getInstance().handler(domainEvent.getEvent()); + try { + EventTraceContext.getInstance().createEventKey(traceId); + ApplicationHandlerUtils.getInstance().handler(domainEvent.getEvent()); + } finally { + EventTraceContext.getInstance().checkEventState(); + } } else { executorService.execute(() -> { - ApplicationHandlerUtils.getInstance().handler(domainEvent.getEvent()); + try { + EventTraceContext.getInstance().createEventKey(traceId); + ApplicationHandlerUtils.getInstance().handler(domainEvent.getEvent()); + } finally { + EventTraceContext.getInstance().checkEventState(); + } }); } } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/SpringHandlerConfiguration.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/SpringHandlerConfiguration.java similarity index 89% rename from springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/SpringHandlerConfiguration.java rename to springboot-starter/src/main/java/com/codingapi/springboot/framework/event/SpringHandlerConfiguration.java index 0f5c989c..e3afeb12 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/SpringHandlerConfiguration.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/SpringHandlerConfiguration.java @@ -1,4 +1,4 @@ -package com.codingapi.springboot.framework.handler; +package com.codingapi.springboot.framework.event; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java new file mode 100644 index 00000000..68462e73 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java @@ -0,0 +1,17 @@ +package com.codingapi.springboot.framework.exception; + +import lombok.Getter; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +public class EventException extends RuntimeException { + + private final List error; + + public EventException(List error) { + super(error.stream().map(Exception::getMessage).collect(Collectors.joining("\n"))); + this.error = error; + } +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventLoopException.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventLoopException.java new file mode 100644 index 00000000..cb17f046 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventLoopException.java @@ -0,0 +1,17 @@ +package com.codingapi.springboot.framework.exception; + +import com.codingapi.springboot.framework.event.IEvent; +import lombok.Getter; + +import java.util.List; + +@Getter +public class EventLoopException extends RuntimeException { + + private final List> stack; + + public EventLoopException(List> stack, IEvent event) { + super("event loop error current event class:" + event.getClass() + ", history event stack:" + stack); + this.stack = stack; + } +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/RandomGenerator.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/RandomGenerator.java new file mode 100644 index 00000000..d81723c6 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/RandomGenerator.java @@ -0,0 +1,22 @@ +package com.codingapi.springboot.framework.utils; + +import java.util.UUID; + +public class RandomGenerator { + + public static String generateUUID() { + return UUID.randomUUID().toString(); + } + + + public static String randomString(int length) { + String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < length; i++) { + int number = (int) (Math.random() * str.length()); + sb.append(str.charAt(number)); + } + return sb.toString(); + } + +} diff --git a/springboot-starter/src/main/resources/META-INF/spring.factories b/springboot-starter/src/main/resources/META-INF/spring.factories index 5765e102..3fd6c549 100644 --- a/springboot-starter/src/main/resources/META-INF/spring.factories +++ b/springboot-starter/src/main/resources/META-INF/spring.factories @@ -2,6 +2,6 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.codingapi.springboot.framework.AutoConfiguration,\ com.codingapi.springboot.framework.event.SpringEventConfiguration,\ com.codingapi.springboot.framework.exception.ExceptionConfiguration,\ -com.codingapi.springboot.framework.handler.HandlerBeanDefinitionRegistrar,\ -com.codingapi.springboot.framework.handler.SpringHandlerConfiguration,\ -com.codingapi.springboot.framework.servlet.BasicHandlerExceptionResolverConfiguration \ No newline at end of file +com.codingapi.springboot.framework.event.HandlerBeanDefinitionRegistrar,\ +com.codingapi.springboot.framework.event.SpringHandlerConfiguration,\ +com.codingapi.springboot.framework.servlet.BasicHandlerExceptionResolverConfiguration diff --git a/springboot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/springboot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 39319e71..8aa6f4cd 100644 --- a/springboot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/springboot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,6 +1,6 @@ com.codingapi.springboot.framework.AutoConfiguration com.codingapi.springboot.framework.event.SpringEventConfiguration com.codingapi.springboot.framework.exception.ExceptionConfiguration -com.codingapi.springboot.framework.handler.HandlerBeanDefinitionRegistrar -com.codingapi.springboot.framework.handler.SpringHandlerConfiguration -com.codingapi.springboot.framework.servlet.BasicHandlerExceptionResolverConfiguration \ No newline at end of file +com.codingapi.springboot.framework.event.HandlerBeanDefinitionRegistrar +com.codingapi.springboot.framework.event.SpringHandlerConfiguration +com.codingapi.springboot.framework.servlet.BasicHandlerExceptionResolverConfiguration diff --git a/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoChangeLogHandler.java b/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoChangeLogHandler.java index 0f2d3bb1..f1efb83b 100644 --- a/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoChangeLogHandler.java +++ b/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoChangeLogHandler.java @@ -1,6 +1,8 @@ package com.codingapi.springboot.framework.handler; import com.codingapi.springboot.framework.event.DemoChangeEvent; +import com.codingapi.springboot.framework.event.Handler; +import com.codingapi.springboot.framework.event.IHandler; import lombok.extern.slf4j.Slf4j; @Slf4j diff --git a/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoCreateHandler.java b/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoCreateHandler.java index f48c9fcc..01ab9aa5 100644 --- a/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoCreateHandler.java +++ b/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoCreateHandler.java @@ -1,6 +1,8 @@ package com.codingapi.springboot.framework.handler; import com.codingapi.springboot.framework.domain.event.DomainCreateEvent; +import com.codingapi.springboot.framework.event.Handler; +import com.codingapi.springboot.framework.event.IHandler; import lombok.extern.slf4j.Slf4j; @Slf4j diff --git a/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoDeleteHandler.java b/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoDeleteHandler.java index 89885b16..6f02be80 100644 --- a/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoDeleteHandler.java +++ b/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoDeleteHandler.java @@ -1,6 +1,8 @@ package com.codingapi.springboot.framework.handler; import com.codingapi.springboot.framework.domain.event.DomainDeleteEvent; +import com.codingapi.springboot.framework.event.Handler; +import com.codingapi.springboot.framework.event.IHandler; import lombok.extern.slf4j.Slf4j; @Slf4j diff --git a/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoPersistEventHandler.java b/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoPersistEventHandler.java index cb3dae62..2d18934f 100644 --- a/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoPersistEventHandler.java +++ b/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/DemoPersistEventHandler.java @@ -1,11 +1,13 @@ package com.codingapi.springboot.framework.handler; import com.codingapi.springboot.framework.domain.event.DomainPersistEvent; +import com.codingapi.springboot.framework.event.Handler; +import com.codingapi.springboot.framework.event.IHandler; import lombok.extern.slf4j.Slf4j; @Slf4j @Handler -public class DemoPersistEventHandler implements IHandler{ +public class DemoPersistEventHandler implements IHandler { @Override public void handler(DomainPersistEvent event) { diff --git a/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/EntityFiledChangeHandler.java b/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/EntityFiledChangeHandler.java index b6bf661f..d4fb12b0 100644 --- a/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/EntityFiledChangeHandler.java +++ b/springboot-starter/src/test/java/com/codingapi/springboot/framework/handler/EntityFiledChangeHandler.java @@ -1,11 +1,13 @@ package com.codingapi.springboot.framework.handler; import com.codingapi.springboot.framework.domain.event.DomainChangeEvent; +import com.codingapi.springboot.framework.event.Handler; +import com.codingapi.springboot.framework.event.IHandler; import lombok.extern.slf4j.Slf4j; @Slf4j @Handler -public class EntityFiledChangeHandler implements IHandler{ +public class EntityFiledChangeHandler implements IHandler { @Override public void handler(DomainChangeEvent event) { From bae16217bef88c749159a986b61195ec497082c9 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 9 Nov 2024 10:53:22 +0800 Subject: [PATCH 053/129] add flow & update event --- pom.xml | 41 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/README.md | 39 + springboot-starter-flow/pom.xml | 52 ++ .../springboot/flow/FlowConfiguration.java | 17 + .../flow/FlowFrameworkRegister.java | 17 + .../flow/bind/BindDataSnapshot.java | 55 ++ .../springboot/flow/bind/IBindData.java | 18 + .../flow/build/FlowWorkBuilder.java | 123 +++ .../springboot/flow/build/SchemaReader.java | 92 ++ .../springboot/flow/content/FlowSession.java | 77 ++ .../flow/content/FlowSessionBeanProvider.java | 30 + .../springboot/flow/domain/FlowNode.java | 303 +++++++ .../springboot/flow/domain/FlowRelation.java | 168 ++++ .../springboot/flow/domain/FlowWork.java | 332 +++++++ .../springboot/flow/domain/Opinion.java | 78 ++ .../springboot/flow/em/ApprovalType.java | 26 + .../flow/em/FlowSourceDirection.java | 30 + .../springboot/flow/em/FlowStatus.java | 27 + .../springboot/flow/em/FlowType.java | 30 + .../springboot/flow/em/NodeType.java | 30 + .../springboot/flow/error/ErrTrigger.java | 36 + .../springboot/flow/error/ErrorResult.java | 17 + .../springboot/flow/error/NodeResult.java | 16 + .../springboot/flow/error/OperatorResult.java | 25 + .../flow/event/FlowApprovalEvent.java | 88 ++ .../flow/generator/TitleGenerator.java | 47 + .../flow/matcher/OperatorMatcher.java | 115 +++ .../springboot/flow/pojo/FlowDetail.java | 95 ++ .../springboot/flow/pojo/FlowResult.java | 26 + .../flow/query/FlowRecordQuery.java | 55 ++ .../springboot/flow/record/FlowBackup.java | 61 ++ .../springboot/flow/record/FlowProcess.java | 42 + .../springboot/flow/record/FlowRecord.java | 417 +++++++++ .../flow/repository/FlowBackupRepository.java | 33 + .../repository/FlowBindDataRepository.java | 31 + .../repository/FlowOperatorRepository.java | 29 + .../repository/FlowProcessRepository.java | 16 + .../flow/repository/FlowRecordRepository.java | 70 ++ .../flow/repository/FlowWorkRepository.java | 18 + .../flow/script/GroovyShellContext.java | 87 ++ .../serializable/FlowNodeSerializable.java | 94 ++ .../FlowRelationSerializable.java | 82 ++ .../serializable/FlowWorkSerializable.java | 140 +++ .../flow/service/FlowDirectionService.java | 126 +++ .../service/FlowRecordBuilderService.java | 251 ++++++ .../flow/service/FlowRecordService.java | 192 ++++ .../springboot/flow/service/FlowService.java | 522 +++++++++++ .../springboot/flow/trigger/OutTrigger.java | 44 + .../springboot/flow/user/IFlowOperator.java | 36 + .../springboot/flow/utils/Sha256Utils.java | 25 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../springboot/flow/FlowTestApplication.java | 12 + .../codingapi/springboot/flow/flow/Leave.java | 24 + .../repository/FlowBackupRepositoryImpl.java | 29 + .../FlowBindDataRepositoryImpl.java | 38 + .../repository/FlowProcessRepositoryImpl.java | 39 + .../repository/FlowRecordRepositoryImpl.java | 104 +++ .../repository/FlowWorkRepositoryImpl.java | 34 + .../flow/repository/LeaveRepository.java | 18 + .../flow/repository/UserRepository.java | 39 + .../flow/script/GroovyShellContextTest.java | 30 + .../springboot/flow/test/BuildTest.java | 49 ++ .../springboot/flow/test/ErrorTest.java | 218 +++++ .../springboot/flow/test/FlowTest.java | 821 ++++++++++++++++++ .../springboot/flow/test/FlowTest2.java | 113 +++ .../flow/test/MultiRelationFlowTest.java | 314 +++++++ .../springboot/flow/test/QueryTest.java | 540 ++++++++++++ .../springboot/flow/test/ScriptBuildTest.java | 43 + .../springboot/flow/test/ScriptTest.java | 72 ++ .../springboot/flow/test/SignTest.java | 415 +++++++++ .../codingapi/springboot/flow/user/User.java | 46 + springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../event/ApplicationHandlerUtils.java | 38 +- .../springboot/framework/event/IEvent.java | 1 - .../springboot/framework/event/IHandler.java | 17 +- 77 files changed, 7452 insertions(+), 30 deletions(-) create mode 100644 springboot-starter-flow/README.md create mode 100644 springboot-starter-flow/pom.xml create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/FlowConfiguration.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/FlowFrameworkRegister.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/BindDataSnapshot.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSessionBeanProvider.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowRelation.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/ApprovalType.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowSourceDirection.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowStatus.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/NodeType.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/ErrTrigger.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/ErrorResult.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/NodeResult.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/OperatorResult.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/generator/TitleGenerator.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowBackup.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowProcess.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowBackupRepository.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowBindDataRepository.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowOperatorRepository.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowWorkRepository.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/script/GroovyShellContext.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowRelationSerializable.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordBuilderService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/trigger/OutTrigger.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/user/IFlowOperator.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/utils/Sha256Utils.java create mode 100644 springboot-starter-flow/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/FlowTestApplication.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowBackupRepositoryImpl.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowBindDataRepositoryImpl.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowWorkRepositoryImpl.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/LeaveRepository.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/UserRepository.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/script/GroovyShellContextTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/BuildTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/QueryTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/user/User.java diff --git a/pom.xml b/pom.xml index f93e9daf..ceb40070 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.8.11 + 2.9.0 https://github.com/codingapi/springboot-framewrok springboot-parent @@ -31,18 +31,20 @@ 1.6.13 3.1.0 ${project.version} - 2.0.42 - 0.12.5 - 2.15.0 + 2.0.53 + 0.12.6 + 2.17.0 + 3.17.0 1.8.1 - 1.11.0 + 1.12.0 0.10.2 0.9.16 - 1.77 + 1.79 1.2.0 2.2 - 4.0.15 - 2.2.224 + 4.0.24 + 2.3.232 + 5.6.2 @@ -75,6 +77,12 @@ + + com.esotericsoftware + kryo + ${esotericsoftware.kryo.version} + + com.h2database h2 @@ -99,6 +107,18 @@ ${commons-crypto.version} + + commons-io + commons-io + ${commons-io.version} + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + org.perf4j perf4j @@ -249,6 +269,7 @@ springboot-starter + springboot-starter-flow springboot-starter-security springboot-starter-data-fast @@ -260,6 +281,7 @@ springboot-starter + springboot-starter-flow springboot-starter-security springboot-starter-data-fast @@ -289,7 +311,7 @@ org.openclover clover-maven-plugin - 4.4.1 + 4.5.2 true true @@ -309,6 +331,7 @@ springboot-starter + springboot-starter-flow springboot-starter-security springboot-starter-data-fast diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index a2fc1cdf..012a2759 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.8.11 + 2.9.0 4.0.0 diff --git a/springboot-starter-flow/README.md b/springboot-starter-flow/README.md new file mode 100644 index 00000000..0bea8953 --- /dev/null +++ b/springboot-starter-flow/README.md @@ -0,0 +1,39 @@ +# springboot-starter-flow 流程引擎 + +流程引擎支持的功能需要包括: + +支持的功能如下: + +流程管理 +1. build模式的流程设计 +2. schema模式的流程设计 +3. 流程的启用与禁用 +4. 流程快照的存储 + +流程设计 +1. 支持自定义节点与节点关系 +2. 支持自定义节点的操作用户,可通过groovy脚本定义 +3. 支持流程消息标题的自定义能力,可通过groovy脚本定义 +4. 支持流程异常状态的自定义能力,可通过groovy脚本定义 +5. 提供流程操作过程中的事件,可以做业务定制与延伸 + + +流程能力 +1. 流程发起 + 在设计完成以后并启用以后,可通过FlowService对象发起流程。 +2. 流程审批 + 流程的审批支持同意与拒绝,以及审批意见的填写。 +3. 流程撤销 + 流程的发起以后,在下一节点的流程待审批且未读之前可以撤销流程。 +4. 流程转办 + 流程的审批过程中,可以将流程转办给其他人员审批。 +5. 流程委托 + 可设置用户的委托人,委托人可以代理委托人审批流程。 +6. 流程催办 + 流程的审批过程中,可以催办审批人员,催办将会发送催办事件消息。 +7. 流程查询 + 可以查询流程的待办、已办、超时、延期、全部流程等数据。 +8. 流程干预 + 设置流程管理员的人员,可以对流程进行干预,可以直接对其他人的流程进行审批。 +9. 流程延期 + 流程的审批过程中,可以延期流程的审批时间。 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml new file mode 100644 index 00000000..c2d61cc1 --- /dev/null +++ b/springboot-starter-flow/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + springboot-parent + com.codingapi.springboot + 2.9.0 + + + springboot-starter-flow + springboot-starter-flow project for Spring Boot + springboot-starter-flow + + + 8 + + + + + + + com.codingapi.springboot + springboot-starter + + + + com.esotericsoftware + kryo + + + + org.apache.groovy + groovy + + + + org.apache.groovy + groovy-json + + + + org.apache.groovy + groovy-xml + + + + + + + diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/FlowConfiguration.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/FlowConfiguration.java new file mode 100644 index 00000000..7948386e --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/FlowConfiguration.java @@ -0,0 +1,17 @@ +package com.codingapi.springboot.flow; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FlowConfiguration { + + @Bean + @ConditionalOnMissingBean + public FlowFrameworkRegister flowFrameworkRegister(ApplicationContext spring) { + return new FlowFrameworkRegister(spring); + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/FlowFrameworkRegister.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/FlowFrameworkRegister.java new file mode 100644 index 00000000..5fb46b8f --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/FlowFrameworkRegister.java @@ -0,0 +1,17 @@ +package com.codingapi.springboot.flow; + +import com.codingapi.springboot.flow.content.FlowSessionBeanProvider; +import lombok.AllArgsConstructor; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; + +@AllArgsConstructor +public class FlowFrameworkRegister implements InitializingBean { + + private final ApplicationContext application; + + @Override + public void afterPropertiesSet() throws Exception { + FlowSessionBeanProvider.getInstance().register(application); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/BindDataSnapshot.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/BindDataSnapshot.java new file mode 100644 index 00000000..b2d0b1a8 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/BindDataSnapshot.java @@ -0,0 +1,55 @@ +package com.codingapi.springboot.flow.bind; + +import com.alibaba.fastjson.JSONObject; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +/** + * 数据快照 + */ +@Setter +@Getter +@AllArgsConstructor +public class BindDataSnapshot { + + /** + * 数据快照id + */ + private long id; + /** + * 快照信息 + */ + private String snapshot; + /** + * 创建时间 + */ + private long createTime; + + /** + * 数据绑定类名称 + */ + private String clazzName; + + public BindDataSnapshot(long id,IBindData bindData) { + if (bindData == null) { + throw new IllegalArgumentException("bind data is null"); + } + this.snapshot = bindData.toJsonSnapshot(); + this.clazzName = bindData.getClass().getName(); + this.createTime = System.currentTimeMillis(); + this.id = id; + } + + public BindDataSnapshot(IBindData bindData) { + this(0,bindData); + } + + public IBindData toBindData() { + try { + return JSONObject.parseObject(snapshot, (Class) Class.forName(clazzName)); + } catch (Exception e) { + throw new IllegalArgumentException("bind data error"); + } + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java new file mode 100644 index 00000000..6a7287bc --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java @@ -0,0 +1,18 @@ +package com.codingapi.springboot.flow.bind; + +import com.alibaba.fastjson.JSONObject; + +/** + * 数据绑定接口 + */ +public interface IBindData { + + /** + * 数据快照 + * + * @return 数据快照 + */ + default String toJsonSnapshot() { + return JSONObject.toJSONString(this); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java new file mode 100644 index 00000000..08d89bf5 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java @@ -0,0 +1,123 @@ +package com.codingapi.springboot.flow.build; + +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowRelation; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.em.NodeType; +import com.codingapi.springboot.flow.error.ErrTrigger; +import com.codingapi.springboot.flow.generator.TitleGenerator; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.trigger.OutTrigger; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.utils.RandomGenerator; + +/** + * 流程工作构建器 + */ +public class FlowWorkBuilder { + + private FlowWork work = null; + + private FlowWorkBuilder(FlowWork flowWork) { + this.work = flowWork; + } + + + public static FlowWorkBuilder builder(IFlowOperator flowOperator) { + return new FlowWorkBuilder(new FlowWork(flowOperator)); + } + + public FlowWorkBuilder description(String description) { + this.work.setDescription(description); + return this; + } + + public FlowWorkBuilder postponedMax(int postponedMax) { + this.work.setPostponedMax(postponedMax); + return this; + } + + public FlowWorkBuilder title(String title) { + this.work.setTitle(title); + return this; + } + + public FlowWorkBuilder schema(String schema) { + this.work.schema(schema); + return this; + } + + + public Nodes nodes() { + return new Nodes(); + } + + public Relations relations() { + return new Relations(); + } + + public FlowWork build() { + work.enable(); + return work; + } + + + public class Nodes { + + public Nodes node(String id,String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, TitleGenerator titleGenerator, ErrTrigger errTrigger, boolean editable) { + FlowNode node = new FlowNode(id, name, code, view, NodeType.parser(code), approvalType, titleGenerator, operatorMatcher, timeout, errTrigger, editable); + work.addNode(node); + return this; + } + + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher,long timeout, boolean editable) { + return node(RandomGenerator.generateUUID(),name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable); + } + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, boolean editable) { + return node(RandomGenerator.generateUUID(),name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable); + } + + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher) { + return node(name, code, view, approvalType, operatorMatcher, true); + } + + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable) { + return node(RandomGenerator.generateUUID(),name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable); + } + + + public Relations relations() { + return new Relations(); + } + + public FlowWork build() { + work.enable(); + return work; + } + + + } + + public class Relations { + + public Relations relation(String name, String source, String target) { + return relation(name,source,target,OutTrigger.defaultOutTrigger(),1,false); + } + + public Relations relation(String name, String source, String target, OutTrigger outTrigger,int order, boolean back) { + FlowNode from = work.getNodeByCode(source); + FlowNode to = work.getNodeByCode(target); + FlowRelation relation = new FlowRelation(RandomGenerator.generateUUID(), name, from, to, outTrigger,order, back); + work.addRelation(relation); + return this; + } + + public FlowWork build() { + work.enable(); + return work; + } + + + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java new file mode 100644 index 00000000..bb5abd75 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java @@ -0,0 +1,92 @@ +package com.codingapi.springboot.flow.build; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowRelation; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.em.NodeType; +import com.codingapi.springboot.flow.error.ErrTrigger; +import com.codingapi.springboot.flow.generator.TitleGenerator; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.trigger.OutTrigger; +import lombok.Getter; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 流程设计schema读取器 + */ +public class SchemaReader { + + private final JSONObject data; + + @Getter + private final List flowNodes; + @Getter + private final List flowRelations; + + public SchemaReader(String schema) { + this.data = JSONObject.parseObject(schema); + this.flowNodes = new ArrayList<>(); + this.flowRelations = new ArrayList<>(); + this.loadNodes(); + this.loadEdges(); + } + + + private void loadNodes(){ + JSONArray nodes = data.getJSONArray("nodes"); + for (int i = 0; i < nodes.size(); i++) { + JSONObject node = nodes.getJSONObject(i); + JSONObject properties = node.getJSONObject("properties"); + String code = properties.getString("code"); + String operatorMatcher = properties.getString("operatorMatcher"); + String titleGenerator = properties.getString("titleGenerator"); + String name = properties.getString("name"); + boolean editable = properties.getBoolean("editable"); + String view = properties.getString("view"); + String type = properties.getString("type"); + String approvalType = properties.getString("approvalType"); + int timeout = properties.getIntValue("timeout"); + String errTrigger = properties.getString("errTrigger"); + String id = properties.getString("id"); + FlowNode flowNode = new FlowNode(id,name,code,view, NodeType.parser(type),ApprovalType.parser(approvalType),new TitleGenerator(titleGenerator), + new OperatorMatcher(operatorMatcher),timeout, StringUtils.hasLength(errTrigger)?new ErrTrigger(errTrigger):null,editable); + flowNodes.add(flowNode); + } + } + + private FlowNode getFlowNodeById(String id){ + for(FlowNode flowNode:flowNodes){ + if(flowNode.getId().equals(id)){ + return flowNode; + } + } + return null; + } + + private void loadEdges(){ + JSONArray edges = data.getJSONArray("edges"); + for(int i=0;i historyRecords; + private final FlowSessionBeanProvider provider; + + public FlowSession(FlowWork flowWork, FlowNode flowNode, IFlowOperator createOperator, IFlowOperator currentOperator, IBindData bindData, Opinion opinion, List historyRecords) { + this.flowWork = flowWork; + this.flowNode = flowNode; + this.createOperator = createOperator; + this.currentOperator = currentOperator; + this.bindData = bindData; + this.opinion = opinion; + this.historyRecords = historyRecords; + this.provider = FlowSessionBeanProvider.getInstance(); + } + + + public Object getBean(String beanName) { + return provider.getBean(beanName); + } + + /** + * 创建节点结果 + * + * @param nodeCode 节点code + * @return 节点结果 + */ + public NodeResult createNodeErrTrigger(String nodeCode) { + return new NodeResult(nodeCode); + } + + /** + * 创建操作者结果 + * + * @param operatorIds 操作者id + * @return 操作者结果 + */ + public OperatorResult createOperatorErrTrigger(List operatorIds) { + return new OperatorResult(operatorIds); + } + + /** + * 创建操作者结果 + * + * @param operatorIds 操作者id + * @return 操作者结果 + */ + public OperatorResult createOperatorErrTrigger(long... operatorIds) { + return new OperatorResult(operatorIds); + } + + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSessionBeanProvider.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSessionBeanProvider.java new file mode 100644 index 00000000..58b9351d --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSessionBeanProvider.java @@ -0,0 +1,30 @@ +package com.codingapi.springboot.flow.content; + +import lombok.Getter; +import org.springframework.context.ApplicationContext; + +/** + * 流程回话 spring bean 提供者 + */ +public class FlowSessionBeanProvider { + + @Getter + private static final FlowSessionBeanProvider instance = new FlowSessionBeanProvider(); + + private FlowSessionBeanProvider() { + } + + private ApplicationContext spring; + + public void register(ApplicationContext spring) { + this.spring = spring; + } + + public Object getBean(String beanName) { + if (spring != null) { + return spring.getBean(beanName); + } + return null; + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java new file mode 100644 index 00000000..7d9291ed --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java @@ -0,0 +1,303 @@ +package com.codingapi.springboot.flow.domain; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.em.*; +import com.codingapi.springboot.flow.error.ErrTrigger; +import com.codingapi.springboot.flow.error.ErrorResult; +import com.codingapi.springboot.flow.generator.TitleGenerator; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowOperatorRepository; +import com.codingapi.springboot.flow.serializable.FlowNodeSerializable; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.springframework.util.StringUtils; + +import java.util.List; + +/** + * 流程节点 + */ +@Getter +@AllArgsConstructor +public class FlowNode { + + public static final String CODE_START = "start"; + public static final String CODE_OVER = "over"; + + /** + * 节点id + */ + private String id; + + /** + * 节点编码 + */ + private String code; + + /** + * 节点名称 + */ + private String name; + + /** + * 节点标题创建规则 + */ + private TitleGenerator titleGenerator; + + /** + * 节点类型 | 分为发起、审批、结束 + */ + private NodeType type; + + /** + * 节点视图 + */ + private String view; + + /** + * 流程审批类型 | 分为会签、非会签 + */ + private ApprovalType approvalType; + + /** + * 操作者匹配器 + */ + private OperatorMatcher operatorMatcher; + + /** + * 是否可编辑 + */ + private boolean editable; + + /** + * 创建时间 + */ + private long createTime; + /** + * 更新时间 + */ + private long updateTime; + + /** + * 超时时间(毫秒) + */ + private long timeout; + + /** + * 异常触发器,当流程发生异常时异常通常是指找不到审批人,将会触发异常触发器,异常触发器可以是一个节点 + */ + @Setter + private ErrTrigger errTrigger; + + + public void verify(){ + if (this.titleGenerator == null) { + throw new IllegalArgumentException("titleGenerator is null"); + } + if (this.operatorMatcher == null) { + throw new IllegalArgumentException("operatorMatcher is null"); + } + if(timeout<0){ + throw new IllegalArgumentException("timeout is less than 0"); + } + if(!StringUtils.hasLength(id)){ + throw new IllegalArgumentException("id is empty"); + } + if(!StringUtils.hasLength(code)){ + throw new IllegalArgumentException("code is empty"); + } + } + + + /** + * 从序列化对象中创建节点 + * + * @return FlowNodeSerializable 序列号节点 + */ + public FlowNodeSerializable toSerializable() { + return new FlowNodeSerializable( + this.id, + this.code, + this.name, + this.titleGenerator.getScript(), + this.type, + this.view, + this.approvalType, + this.operatorMatcher.getScript(), + this.editable, + this.createTime, + this.updateTime, + this.timeout, + this.errTrigger == null ? null : this.errTrigger.getScript() + ); + } + + + public FlowNode(String id, + String name, + String code, + String view, + NodeType type, + ApprovalType approvalType, + TitleGenerator titleGenerator, + OperatorMatcher operatorMatcher, + long timeout, + ErrTrigger errTrigger, + boolean editable) { + this.id = id; + this.code = code; + this.name = name; + this.titleGenerator = titleGenerator; + this.type = type; + this.view = view; + this.approvalType = approvalType; + this.operatorMatcher = operatorMatcher; + this.createTime = System.currentTimeMillis(); + this.updateTime = System.currentTimeMillis(); + this.errTrigger = errTrigger; + this.timeout = timeout; + this.editable = editable; + } + + + /** + * 加载节点的操作者 + * + * @param flowSession 操作内容 + * @return 是否匹配 + */ + public List loadFlowNodeOperator(FlowSession flowSession, FlowOperatorRepository flowOperatorRepository) { + return flowOperatorRepository.findByIds(this.operatorMatcher.matcher(flowSession)); + } + + + /** + * 创建流程记录 + * + * @param workId 流程设计id + * @param processId 流程id + * @param preId 上一条流程记录id + * @param title 流程标题 + * @param createOperator 流程操作者 + * @param currentOperator 当前操作者 + * @param snapshot 快照数据 + * @return 流程记录 + */ + public FlowRecord createRecord(long workId, + String processId, + long preId, + String title, + IFlowOperator createOperator, + IFlowOperator currentOperator, + BindDataSnapshot snapshot + ) { + + // 当前操作者存在委托人时,才需要寻找委托人 + IFlowOperator flowOperator = currentOperator; + while (flowOperator.entrustOperator() != null) { + //寻找委托人 + flowOperator = flowOperator.entrustOperator(); + } + FlowRecord record = new FlowRecord(); + record.setProcessId(processId); + record.setNodeCode(this.code); + record.setCreateTime(System.currentTimeMillis()); + record.setWorkId(workId); + record.setFlowStatus(FlowStatus.RUNNING); + record.setPostponedCount(0); + record.setCreateOperator(createOperator); + record.setBindClass(snapshot.getClazzName()); + record.setCurrentOperator(flowOperator); + record.setPreId(preId); + record.setTitle(title); + record.setTimeoutTime(this.loadTimeoutTime()); + record.setFlowType(FlowType.TODO); + record.setErrMessage(null); + record.setSnapshotId(snapshot.getId()); + return record; + } + + + /** + * 获取超时时间 + * + * @return 超时时间 + */ + private long loadTimeoutTime() { + if (this.timeout > 0) { + return System.currentTimeMillis() + this.timeout; + } + return 0; + } + + /** + * 是否有任意操作者匹配 + */ + public boolean isAnyOperatorMatcher() { + return operatorMatcher.isAny(); + } + + /** + * 异常匹配 + * + * @param flowSession 操作内容 + */ + public ErrorResult errMatcher(FlowSession flowSession) { + if (errTrigger != null) { + return errTrigger.trigger(flowSession); + } + return null; + } + + /** + * 是否有异常触发器 + * + * @return 是否有异常触发器 + */ + public boolean hasErrTrigger() { + return errTrigger != null; + } + + /** + * 生成标题 + * + * @param flowSession 流程内容 + * @return 标题 + */ + public String generateTitle(FlowSession flowSession) { + return titleGenerator.generate(flowSession); + } + + + /** + * 是否会签节点 + */ + public boolean isSign() { + return approvalType == ApprovalType.SIGN; + } + + /** + * 是否非会签节点 + */ + public boolean isUnSign() { + return approvalType == ApprovalType.UN_SIGN; + } + + /** + * 是否结束节点 + */ + public boolean isOverNode() { + return CODE_OVER.equals(this.code); + } + + /** + * 是否开始节点 + */ + public boolean isStartNode() { + return CODE_START.equals(this.code); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowRelation.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowRelation.java new file mode 100644 index 00000000..c93dead9 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowRelation.java @@ -0,0 +1,168 @@ +package com.codingapi.springboot.flow.domain; + +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.em.NodeType; +import com.codingapi.springboot.flow.serializable.FlowRelationSerializable; +import com.codingapi.springboot.flow.trigger.OutTrigger; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.util.StringUtils; + +import java.util.List; + +/** + * 流程关系 + */ +@Getter +@AllArgsConstructor +public class FlowRelation { + + /** + * 关系id + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 源节点 + */ + private FlowNode source; + + /** + * 目标节点 + */ + private FlowNode target; + + /** + * 排序 + */ + private int order; + + /** + * 是否退回 + */ + private boolean back; + + /** + * 出口触发器 + */ + private OutTrigger outTrigger; + + + /** + * 创建时间 + */ + private long createTime; + + /** + * 修改时间 + */ + private long updateTime; + + + /** + * 序列化 + * + * @return 序列化对象 + */ + public FlowRelationSerializable toSerializable() { + return new FlowRelationSerializable(id, + name, + source.getId(), + target.getId(), + order, + back, + outTrigger.getScript(), + createTime, + updateTime + ); + } + + /** + * 匹配节点 + * + * @param nodeCode 节点编码 + * @return 是否匹配 + */ + public boolean sourceMatcher(String nodeCode) { + return source.getCode().equals(nodeCode); + } + + + /** + * 重新排序 + * + * @param order 排序 + */ + public void resort(int order) { + this.order = order; + } + + + public FlowRelation(String id, String name, FlowNode source, FlowNode target, OutTrigger outTrigger, int order, boolean back) { + this.id = id; + this.name = name; + this.source = source; + this.target = target; + this.outTrigger = outTrigger; + this.order = order; + this.back = back; + this.createTime = System.currentTimeMillis(); + this.updateTime = System.currentTimeMillis(); + } + + /** + * 触发条件 + * + * @param flowSession 流程内容 + * @return 下一个节点 + */ + public FlowNode trigger(FlowSession flowSession) { + if (outTrigger.trigger(flowSession)) { + return target; + } + return null; + } + + + /** + * 验证 + */ + public void verify() { + if (!StringUtils.hasLength(id)) { + throw new RuntimeException("id is null"); + } + + if (source == null || target == null) { + throw new RuntimeException("source or target is null"); + } + + if (outTrigger == null) { + throw new RuntimeException("outTrigger is null"); + } + + if(source.getCode().equals(target.getCode())){ + throw new RuntimeException("source node code is equals target node code"); + } + + if(back){ + if(source.getType() != NodeType.APPROVAL){ + throw new RuntimeException("source node type is not approval"); + } + } + } + + public void verifyNodes(List nodes) { + if (nodes.stream().noneMatch(node -> node.getId().equals(source.getId()))) { + throw new RuntimeException("source node is not exists"); + } + + if (nodes.stream().noneMatch(node -> node.getId().equals(target.getId()))) { + throw new RuntimeException("target node is not exists"); + } + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java new file mode 100644 index 00000000..377aedd2 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java @@ -0,0 +1,332 @@ +package com.codingapi.springboot.flow.domain; + +import com.codingapi.springboot.flow.build.SchemaReader; +import com.codingapi.springboot.flow.serializable.FlowWorkSerializable; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.utils.RandomGenerator; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 流程设计 + */ +@Getter +@AllArgsConstructor +public class FlowWork { + + /** + * 流程的设计id + */ + @Setter + private long id; + + /** + * 流程编码 (唯一值) + */ + @Setter + private String code; + + /** + * 流程标题 + */ + @Setter + private String title; + /** + * 流程描述 + */ + @Setter + private String description; + /** + * 流程创建者 + */ + private IFlowOperator createUser; + /** + * 创建时间 + */ + private long createTime; + /** + * 更新时间 + * 也是流程的版本号 + */ + private long updateTime; + /** + * 是否启用 + */ + private boolean enable; + + /** + * 最大延期次数 + */ + @Setter + private int postponedMax; + + /** + * 流程的节点(发起节点) + */ + private List nodes; + + /** + * 流程的关系 + */ + private List relations; + + /** + * 界面设计脚本 + */ + private String schema; + + /** + * 构造函数 + * + * @param createUser 创建者 + */ + public FlowWork(IFlowOperator createUser) { + this.createUser = createUser; + this.createTime = System.currentTimeMillis(); + this.updateTime = System.currentTimeMillis(); + this.nodes = new ArrayList<>(); + this.relations = new ArrayList<>(); + this.enable = false; + this.postponedMax = 1; + this.code = RandomGenerator.randomString(8); + } + + + /** + * 流程设计复制 + * @return FlowWork 流程设计 + */ + public FlowWork copy(){ + if(!StringUtils.hasLength(schema)){ + throw new IllegalArgumentException("schema is empty"); + } + String schema = this.getSchema(); + for(FlowNode flowNode:this.getNodes()){ + String newId = RandomGenerator.generateUUID(); + schema = schema.replaceAll(flowNode.getId(),newId); + } + + for(FlowRelation relation:this.getRelations()){ + String newId = RandomGenerator.generateUUID(); + schema = schema.replaceAll(relation.getId(),newId); + } + + FlowWork flowWork = new FlowWork(this.createUser); + flowWork.setDescription(this.getDescription()); + flowWork.setTitle(this.getTitle()); + flowWork.setCode(RandomGenerator.randomString(8)); + flowWork.setPostponedMax(this.getPostponedMax()); + flowWork.schema(schema); + return flowWork; + } + + + public FlowWork(String code,String title, String description, int postponedMax, IFlowOperator createUser) { + this.title = title; + this.code = code; + this.description = description; + this.postponedMax = postponedMax; + this.createUser = createUser; + this.createTime = System.currentTimeMillis(); + this.updateTime = System.currentTimeMillis(); + this.nodes = new ArrayList<>(); + this.relations = new ArrayList<>(); + this.enable = false; + } + + + public void verify() { + if (this.nodes == null || this.nodes.isEmpty()) { + throw new IllegalArgumentException("nodes is empty"); + } + if (this.relations == null || this.relations.isEmpty()) { + throw new IllegalArgumentException("relations is empty"); + } + if (!StringUtils.hasLength(title)) { + throw new IllegalArgumentException("title is empty"); + } + if (!StringUtils.hasLength(code)) { + throw new IllegalArgumentException("code is empty"); + } + + this.verifyNodes(); + this.verifyRelations(); + this.checkRelation(); + } + + + private void checkRelation() { + FlowNode startNode = getNodeByCode(FlowNode.CODE_START); + if (startNode == null) { + throw new IllegalArgumentException("start node is not exist"); + } + FlowNode overNode = getNodeByCode(FlowNode.CODE_OVER); + if (overNode == null) { + throw new IllegalArgumentException("over node is not exist"); + } + + List sourceCodes = new ArrayList<>(); + List targetCodes = new ArrayList<>(); + for (FlowRelation relation : relations) { + sourceCodes.add(relation.getSource().getCode()); + targetCodes.add(relation.getTarget().getCode()); + } + + if (!sourceCodes.contains(FlowNode.CODE_START)) { + throw new IllegalArgumentException("start node relation is not exist"); + } + + if (!targetCodes.contains(FlowNode.CODE_OVER)) { + throw new IllegalArgumentException("over node relation is not exist"); + } + + } + + + private void verifyNodes() { + List nodeCodes = new ArrayList<>(); + + for (FlowNode node : nodes) { + node.verify(); + if (nodeCodes.contains(node.getCode())) { + throw new IllegalArgumentException("node code is exist"); + } + nodeCodes.add(node.getCode()); + } + } + + + private void verifyRelations() { + for (FlowRelation relation : relations) { + relation.verify(); + + relation.verifyNodes(nodes); + } + } + + + /** + * 序列化 + * + * @return FlowSerializable 流程序列化对象 + */ + public FlowWorkSerializable toSerializable() { + return new FlowWorkSerializable( + id, + code, + title, + description, + createUser.getUserId(), + createTime, + updateTime, + enable, + postponedMax, + nodes.stream().map(FlowNode::toSerializable).collect(Collectors.toCollection(ArrayList::new)), + relations.stream().map(FlowRelation::toSerializable).collect(Collectors.toCollection(ArrayList::new))); + } + + + /** + * schema解析流程设计 + * + * @param schema schema + */ + public void schema(String schema) { + SchemaReader schemaReader = new SchemaReader(schema); + this.relations = schemaReader.getFlowRelations(); + this.nodes = schemaReader.getFlowNodes(); + this.schema = schema; + this.verify(); + this.updateTime = System.currentTimeMillis(); + } + + /** + * 添加节点 + * + * @param node 节点 + */ + public void addNode(FlowNode node) { + List codes = nodes.stream().map(FlowNode::getCode).collect(Collectors.toList()); + if (codes.contains(node.getCode())) { + throw new IllegalArgumentException("node code is exist"); + } + nodes.add(node); + this.updateTime = System.currentTimeMillis(); + } + + /** + * 添加关系 + * + * @param relation 关系 + */ + public void addRelation(FlowRelation relation) { + relations.add(relation); + this.updateTime = System.currentTimeMillis(); + } + + + /** + * 获取节点 + * + * @param code 节点编码 + * @return 节点 + */ + public FlowNode getNodeByCode(String code) { + for (FlowNode node : nodes) { + if (node.getCode().equals(code)) { + return node; + } + } + return null; + } + + + /** + * 获取开始节点 + * + * @return 开始节点 + */ + public FlowNode getStartNode() { + return getNodeByCode(FlowNode.CODE_START); + } + + + /** + * 是否存在退回关系 + */ + public boolean hasBackRelation() { + return relations.stream().anyMatch(FlowRelation::isBack); + } + + + /** + * 启用检测 + */ + public void enableValidate() { + if (!this.isEnable()) { + throw new IllegalArgumentException("flow work is disable"); + } + } + + + /** + * 启用 + */ + public void enable() { + this.verify(); + this.enable = true; + } + + /** + * 禁用 + */ + public void disbale() { + this.enable = false; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java new file mode 100644 index 00000000..3f3321ae --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java @@ -0,0 +1,78 @@ +package com.codingapi.springboot.flow.domain; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +/** + * 审批意见 + */ +@Getter +@Setter +@ToString +@NoArgsConstructor +public class Opinion { + + // 默认审批(人工审批) + public static final int TYPE_DEFAULT = 0; + // 系统自动审批 + public static final int TYPE_AUTO = 1; + + + // 审批结果 暂存 + public static final int RESULT_SAVE = 0; + // 审批结果 转办 + public static final int RESULT_TRANSFER = 1; + // 审批结果 通过 + public static final int RESULT_PASS = 2; + // 审批结果 驳回 + public static final int RESULT_REJECT = 3; + + /** + * 审批意见 + */ + private String advice; + /** + * 审批结果 + */ + private int result; + /** + * 意见类型 + */ + private int type; + + public Opinion(String advice, int result, int type) { + this.advice = advice; + this.result = result; + this.type = type; + } + + public static Opinion save(String advice) { + return new Opinion(advice, RESULT_SAVE, TYPE_DEFAULT); + } + + public static Opinion pass(String advice) { + return new Opinion(advice, RESULT_PASS, TYPE_DEFAULT); + } + + public static Opinion reject(String advice) { + return new Opinion(advice, RESULT_REJECT, TYPE_DEFAULT); + } + + public static Opinion transfer(String advice) { + return new Opinion(advice, RESULT_TRANSFER, TYPE_DEFAULT); + } + + public static Opinion unSignAutoSuccess() { + return new Opinion("非会签自动审批", RESULT_PASS, TYPE_AUTO); + } + + public boolean isSuccess() { + return result == RESULT_PASS; + } + + public boolean isReject() { + return result == RESULT_REJECT; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/ApprovalType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/ApprovalType.java new file mode 100644 index 00000000..60747587 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/ApprovalType.java @@ -0,0 +1,26 @@ +package com.codingapi.springboot.flow.em; + +/** + * 审批类型:会签与非会签 + */ +public enum ApprovalType { + + /** + * 会签 + */ + SIGN, + /** + * 非会签 + */ + UN_SIGN; + + + public static ApprovalType parser(String approvalType) { + for(ApprovalType type:values()){ + if(type.name().equalsIgnoreCase(approvalType)){ + return type; + } + } + return UN_SIGN; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowSourceDirection.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowSourceDirection.java new file mode 100644 index 00000000..deb82606 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowSourceDirection.java @@ -0,0 +1,30 @@ +package com.codingapi.springboot.flow.em; + +/** + * 流程来源的方式 + * 包括 同意、拒绝、转办 + */ +public enum FlowSourceDirection { + + /** + * 同意 + */ + PASS, + /** + * 拒绝 + */ + REJECT, + /** + * + */ + TRANSFER; + + public static FlowSourceDirection parser(String type){ + for(FlowSourceDirection flowSourceDirection :values()){ + if(flowSourceDirection.name().equalsIgnoreCase(type)){ + return flowSourceDirection; + } + } + return null; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowStatus.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowStatus.java new file mode 100644 index 00000000..7c4bceec --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowStatus.java @@ -0,0 +1,27 @@ +package com.codingapi.springboot.flow.em; + +/** + * 流程状态 + * 进行中、已完成 + */ +public enum FlowStatus { + + /** + * 进行中 + */ + RUNNING, + /** + * 已完成 + */ + FINISH; + + + public static FlowStatus parser(String status) { + for (FlowStatus flowStatus : FlowStatus.values()) { + if (flowStatus.name().equalsIgnoreCase(status)) { + return flowStatus; + } + } + return RUNNING; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java new file mode 100644 index 00000000..abee3ff0 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java @@ -0,0 +1,30 @@ +package com.codingapi.springboot.flow.em; + +/** + * 流程的类型 + */ +public enum FlowType { + + /** + * 待办 + */ + TODO, + /** + * 已办 + */ + DONE, + /** + * 转办 + */ + TRANSFER; + + + public static FlowType parser(String type){ + for(FlowType flowType :values()){ + if(flowType.name().equalsIgnoreCase(type)){ + return flowType; + } + } + return TODO; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/NodeType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/NodeType.java new file mode 100644 index 00000000..ac87e905 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/NodeType.java @@ -0,0 +1,30 @@ +package com.codingapi.springboot.flow.em; + +/** + * 节点类型 + */ +public enum NodeType { + + /** + * 发起 + */ + START, + /** + * 审批 + */ + APPROVAL, + /** + * 结束 + */ + OVER; + + + public static NodeType parser(String type) { + for (NodeType nodeType : values()) { + if (nodeType.name().equalsIgnoreCase(type)) { + return nodeType; + } + } + return APPROVAL; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/ErrTrigger.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/ErrTrigger.java new file mode 100644 index 00000000..fbdd6751 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/ErrTrigger.java @@ -0,0 +1,36 @@ +package com.codingapi.springboot.flow.error; + +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.script.GroovyShellContext; +import lombok.Getter; +import org.springframework.util.StringUtils; + +/** + * 错误触发器 + */ +public class ErrTrigger { + + @Getter + private final String script; + + private final GroovyShellContext.ShellScript runtime; + + + public ErrTrigger(String script) { + if (!StringUtils.hasLength(script)) { + throw new IllegalArgumentException("script is empty"); + } + this.script = script; + this.runtime = GroovyShellContext.getInstance().parse(script); + } + + /** + * 触发 + * + * @param flowSession 流程内容 + */ + public ErrorResult trigger(FlowSession flowSession) { + return (ErrorResult) runtime.invokeMethod("run", flowSession); + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/ErrorResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/ErrorResult.java new file mode 100644 index 00000000..96d8b272 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/ErrorResult.java @@ -0,0 +1,17 @@ +package com.codingapi.springboot.flow.error; + + +/** + * 异常匹配的结果对象 + */ +public abstract class ErrorResult { + + public boolean isNode(){ + return this instanceof NodeResult; + } + + public boolean isOperator(){ + return this instanceof OperatorResult; + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/NodeResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/NodeResult.java new file mode 100644 index 00000000..ebcf5fd0 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/NodeResult.java @@ -0,0 +1,16 @@ +package com.codingapi.springboot.flow.error; + +import lombok.Getter; + +/** + * 节点的异常匹配对象 + */ +@Getter +public class NodeResult extends ErrorResult{ + + private final String node; + + public NodeResult(String node) { + this.node = node; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/OperatorResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/OperatorResult.java new file mode 100644 index 00000000..9467626a --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/error/OperatorResult.java @@ -0,0 +1,25 @@ +package com.codingapi.springboot.flow.error; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 操作人员的异常匹配对象 + */ +@Getter +public class OperatorResult extends ErrorResult { + + private final List operatorIds; + + public OperatorResult(List operatorIds) { + this.operatorIds = operatorIds; + } + + public OperatorResult(long... operatorIds) { + this.operatorIds = new ArrayList<>(); + Arrays.stream(operatorIds).forEach(this.operatorIds::add); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java new file mode 100644 index 00000000..f005767e --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java @@ -0,0 +1,88 @@ +package com.codingapi.springboot.flow.event; + +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.ISyncEvent; +import lombok.Getter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +/** + * 流程审批事件 + */ +@Slf4j +@Getter +@ToString +public class FlowApprovalEvent implements ISyncEvent { + // 创建流程 + public static final int STATE_CREATE = 1; + // 流程审批通过 + public static final int STATE_PASS = 2; + // 流程审批拒绝 + public static final int STATE_REJECT = 3; + // 流程转办 + public static final int STATE_TRANSFER = 4; + // 流程撤销 + public static final int STATE_RECALL = 5; + // 流程完成 + public static final int STATE_FINISH = 6; + // 创建待办 + public static final int STATE_TODO = 7; + // 催办 + public static final int STATE_URGE = 8; + + + private final int state; + private final IFlowOperator operator; + private final FlowRecord flowRecord; + private final FlowWork flowWork; + private final IBindData bindData; + + public FlowApprovalEvent(int state, FlowRecord flowRecord, IFlowOperator operator, FlowWork flowWork, IBindData bindData) { + this.state = state; + this.operator = operator; + this.flowRecord = flowRecord; + this.flowWork = flowWork; + this.bindData = bindData; + log.debug("FlowApprovalEvent:{}", this); + } + + + public boolean match(Class bindDataClass) { + return bindDataClass.isInstance(bindData); + } + + public boolean isUrge() { + return state == STATE_URGE; + } + + public boolean isTodo() { + return state == STATE_TODO; + } + + public boolean isCreate() { + return state == STATE_CREATE; + } + + public boolean isPass() { + return state == STATE_PASS; + } + + public boolean isReject() { + return state == STATE_REJECT; + } + + public boolean isTransfer() { + return state == STATE_TRANSFER; + } + + public boolean isRecall() { + return state == STATE_RECALL; + } + + public boolean isFinish() { + return state == STATE_FINISH; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/generator/TitleGenerator.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/generator/TitleGenerator.java new file mode 100644 index 00000000..2fa5f840 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/generator/TitleGenerator.java @@ -0,0 +1,47 @@ +package com.codingapi.springboot.flow.generator; + +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.script.GroovyShellContext; +import lombok.Getter; +import org.springframework.util.StringUtils; + +/** + * 标题生成器 + */ +public class TitleGenerator { + + @Getter + private final String script; + + private final GroovyShellContext.ShellScript runtime; + + public TitleGenerator(String script) { + if (!StringUtils.hasLength(script)) { + throw new IllegalArgumentException("script is empty"); + } + this.script = script; + this.runtime = GroovyShellContext.getInstance().parse(script); + } + + + /** + * 默认标题生成器 + * + * @return 标题生成器 + */ + public static TitleGenerator defaultTitleGenerator() { + return new TitleGenerator("def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}"); + } + + + /** + * 生成标题 + * + * @param flowSession 流程内容 + * @return 标题 + */ + public String generate(FlowSession flowSession) { + return (String) this.runtime.invokeMethod("run", flowSession); + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java new file mode 100644 index 00000000..ae252f0b --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java @@ -0,0 +1,115 @@ +package com.codingapi.springboot.flow.matcher; + +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.script.GroovyShellContext; +import lombok.Getter; +import org.springframework.util.StringUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 操作者匹配器 + */ +public class OperatorMatcher { + + @Getter + private final String script; + + private final int state; + + private final GroovyShellContext.ShellScript runtime; + + // 指定用户 + public static final int STATE_SPECIFY = 1; + // 创建者 + public static final int STATE_CREATOR = 2; + // 任意人 + public static final int STATE_ANY = 3; + + + public boolean isAny() { + return state == STATE_ANY; + } + + public boolean isCreator() { + return state == STATE_CREATOR; + } + + public boolean isSpecify() { + return state == STATE_SPECIFY; + } + + private static int parseState(String script) { + if (script.contains("content.getCurrentOperator().getUserId()")) { + return STATE_ANY; + } else if (script.contains("content.getCreateOperator().getUserId()")) { + return STATE_CREATOR; + } else { + return STATE_SPECIFY; + } + } + + + public OperatorMatcher(String script) { + this(script, parseState(script)); + } + + public OperatorMatcher(String script, int state) { + if (!StringUtils.hasLength(script)) { + throw new IllegalArgumentException("script is empty"); + } + this.script = script; + this.state = state; + this.runtime = GroovyShellContext.getInstance().parse(script); + } + + /** + * 默认操作者匹配器 + * + * @return 操作者匹配器 + */ + public static OperatorMatcher anyOperatorMatcher() { + return new OperatorMatcher("def run(content) {return [content.getCurrentOperator().getUserId()];}", STATE_ANY); + } + + /** + * 指定操作者匹配器 + * + * @param userIds 用户ids + * @return 操作者匹配器 + */ + public static OperatorMatcher specifyOperatorMatcher(long... userIds) { + String userIdsStr = Arrays.stream(userIds).mapToObj(String::valueOf).collect(Collectors.joining(",")); + return new OperatorMatcher("def run(content) {return [" + userIdsStr + "];}", STATE_SPECIFY); + } + + /** + * 创建者操作者匹配器 + * + * @param userIds 用户ids + * @return 操作者匹配器 + */ + public static OperatorMatcher creatorOperatorMatcher() { + return new OperatorMatcher("def run(content) {return [content.getCreateOperator().getUserId()];}", STATE_CREATOR); + } + + /** + * 匹配操作者 + * + * @param flowSession 流程内容 + * @return 是否匹配 + */ + public List matcher(FlowSession flowSession) { + List values = (List) runtime.invokeMethod("run", flowSession); + return values.stream().map(item -> { + if (item instanceof Number) { + return ((Number) item).longValue(); + } else { + return Long.parseLong(item.toString()); + } + }).collect(Collectors.toList()); + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java new file mode 100644 index 00000000..f889f59f --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java @@ -0,0 +1,95 @@ +package com.codingapi.springboot.flow.pojo; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.Getter; + +import java.util.List; +import java.util.stream.Collectors; + + +/** + * 流程详情的阻止对象 + */ +@Getter +public class FlowDetail { + + /** + * 当前流程 + */ + private final FlowRecord flowRecord; + /** + * 流程设计器 + */ + private final FlowWork flowWork; + /** + * 流程节点 + */ + private final FlowNode flowNode; + /** + * 历史流程 + */ + private final List historyRecords; + /** + * 绑定数据 + */ + private final IBindData bindData; + /** + * 全部的操作人 + */ + private final List operators; + + /** + * 创建者 + */ + private final IFlowOperator flowCreator; + + /** + * 创建时间 + */ + private final long flowCreateTime; + + /** + * 流程的意见 + */ + private final List opinions; + + + public FlowDetail(FlowRecord flowRecord, + BindDataSnapshot snapshot, + FlowWork flowWork, + List historyRecords, + List operators) { + this.operators = operators; + this.flowRecord = flowRecord; + this.flowWork = flowWork; + this.bindData = snapshot.toBindData(); + this.historyRecords = historyRecords; + this.opinions = historyRecords.stream().map(FlowOpinion::new).collect(Collectors.toList()); + this.flowCreator = flowRecord.getCreateOperator(); + this.flowCreateTime = flowRecord.getCreateTime(); + this.flowNode = flowWork.getNodeByCode(flowRecord.getNodeCode()); + } + + + @Getter + public final class FlowOpinion { + private final long recordId; + private final Opinion opinion; + private final IFlowOperator operator; + private final long createTime; + + public FlowOpinion(FlowRecord flowRecord) { + this.recordId = flowRecord.getId(); + this.opinion = flowRecord.getOpinion(); + this.operator = flowRecord.getCurrentOperator(); + this.createTime = flowRecord.getUpdateTime(); + } + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java new file mode 100644 index 00000000..4e16e495 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java @@ -0,0 +1,26 @@ +package com.codingapi.springboot.flow.pojo; + +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.record.FlowRecord; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +@Getter +public class FlowResult { + + private final List records; + private final FlowWork flowWork; + + public FlowResult(FlowWork flowWork, List records) { + this.flowWork = flowWork; + this.records = records; + } + + public FlowResult(FlowWork flowWork,FlowRecord flowRecord) { + this.flowWork = flowWork; + this.records = new ArrayList<>(); + this.records.add(flowRecord); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java new file mode 100644 index 00000000..de2e4298 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java @@ -0,0 +1,55 @@ +package com.codingapi.springboot.flow.query; + +import com.codingapi.springboot.flow.record.FlowRecord; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; + +/** + * 流程记录查询服务 + */ +public interface FlowRecordQuery { + + + Page findAll(PageRequest pageRequest); + + /** + * 查看个人的待办数据 + * + * @param operatorId 操作人 + * @return 流程记录 + */ + Page findTodoByOperatorId(long operatorId, PageRequest pageRequest); + + + /** + * 查看个人的已办数据 + * @param operatorId 操作人 + * @return 流程记录 + */ + Page findDoneByOperatorId(long operatorId, PageRequest pageRequest); + + + /** + * 查看个人的发起数据 (含待办与已办) + * @param operatorId 操作人 + * @return 流程记录 + */ + Page findInitiatedByOperatorId(long operatorId, PageRequest pageRequest); + + + /** + * 查看个人的超时的待办流程 + * @param operatorId 操作人 + * @return 流程记录 + */ + Page findTimeoutTodoByOperatorId(long operatorId, PageRequest pageRequest); + + + /** + * 查看个人的延期的待办流程 + * @param operatorId 操作人 + * @return 流程记录 + */ + Page findPostponedTodoByOperatorId(long operatorId, PageRequest pageRequest); + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowBackup.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowBackup.java new file mode 100644 index 00000000..1203e142 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowBackup.java @@ -0,0 +1,61 @@ +package com.codingapi.springboot.flow.record; + +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.repository.FlowOperatorRepository; +import com.codingapi.springboot.flow.serializable.FlowWorkSerializable; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * 流程备份 + */ +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class FlowBackup { + + /** + * 备份id + */ + private long id; + + /** + * 流程的字节码 + */ + private byte[] bytes; + + /** + * 创建时间 + */ + private long createTime; + + /** + * 流程的版本号 + * 以流程的修改时间为准 + */ + private long workVersion; + + /** + * 流程的设计id + */ + private long workId; + + /** + * 恢复流程 + * @param flowOperatorRepository 操作者仓库 + * @return 流程 + */ + public FlowWork resume(FlowOperatorRepository flowOperatorRepository) { + return FlowWorkSerializable.fromSerializable(this.bytes).toFlowWork(flowOperatorRepository); + } + + public FlowBackup(FlowWork flowWork) { + this.bytes = flowWork.toSerializable().toSerializable(); + this.workVersion = flowWork.getUpdateTime(); + this.workId = flowWork.getId(); + this.createTime = System.currentTimeMillis(); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowProcess.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowProcess.java new file mode 100644 index 00000000..b8a4f975 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowProcess.java @@ -0,0 +1,42 @@ +package com.codingapi.springboot.flow.record; + +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.utils.RandomGenerator; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 流程process记录 + */ +@Getter +@AllArgsConstructor +public class FlowProcess { + + /** + * 流程id + */ + private String processId; + + /** + * 创建时间 + */ + private long createTime; + + /** + * 流程的字节码 + */ + private long backupId; + + /** + * 创建者id + */ + private long createOperatorId; + + + public FlowProcess(long backupId, IFlowOperator createOperator) { + this.processId = RandomGenerator.generateUUID(); + this.createTime = System.currentTimeMillis(); + this.backupId = backupId; + this.createOperatorId = createOperator.getUserId(); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java new file mode 100644 index 00000000..41a57d1b --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -0,0 +1,417 @@ +package com.codingapi.springboot.flow.record; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.FlowSourceDirection; +import com.codingapi.springboot.flow.em.FlowStatus; +import com.codingapi.springboot.flow.em.FlowType; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + * 流程记录 + */ +@Setter +@Getter +@ToString +public class FlowRecord { + + /** + * 流程记录id + */ + private long id; + + /** + * 上一个流程记录id + */ + private long preId; + + /** + * 工作id + */ + private long workId; + /** + * 流程id + */ + private String processId; + + /** + * 节点 + */ + private String nodeCode; + + /** + * 流程标题 + */ + private String title; + /** + * 当前操作者 + */ + private IFlowOperator currentOperator; + /** + * 节点状态 | 待办、已办 + */ + private FlowType flowType; + + /** + * 流转产生方式 + * 流程是退回产生的还是通过产生的 + */ + private FlowSourceDirection flowSourceDirection; + + /** + * 创建时间 + */ + private long createTime; + + /** + * 更新时间 + */ + private long updateTime; + + /** + * 完成时间 + */ + private long finishTime; + + /** + * 超时到期时间 + */ + private long timeoutTime; + + /** + * 延期次数 + */ + private int postponedCount; + + /** + * 发起者id + */ + private IFlowOperator createOperator; + /** + * 审批意见 (为办理时为空) + */ + private Opinion opinion; + /** + * 流程状态 | 进行中、已完成 + */ + private FlowStatus flowStatus; + /** + * 异常信息 + */ + private String errMessage; + + /** + * 绑定数据的类 + */ + private String bindClass; + + /** + * 绑定数据的快照 + */ + private long snapshotId; + + /** + * 是否已读 + */ + private boolean read; + + /** + * 是否干预 + */ + private boolean interfere; + + /** + * 被干预的用户 + */ + private IFlowOperator interferedOperator; + + /** + * 已读时间 + */ + private long readTime; + + /** + * 延期时间 + * + * @param postponedMax 最大延期次数 + * @param time 延期时间(毫秒) + */ + public void postponedTime(int postponedMax, long time) { + if (this.postponedCount >= postponedMax) { + throw new IllegalArgumentException("postponed count is max"); + } + this.read(); + if (this.timeoutTime == 0) { + this.timeoutTime = System.currentTimeMillis(); + } + this.timeoutTime += time; + this.postponedCount++; + this.updateTime = System.currentTimeMillis(); + } + + /** + * 是否是发起节点 + */ + public boolean isInitiated() { + return preId == 0 && this.nodeCode.equals(FlowNode.CODE_START); + } + + /** + * 已读 + */ + public void read() { + this.read = true; + this.readTime = System.currentTimeMillis(); + } + + /** + * 是否未读 + */ + public boolean isUnRead() { + return !this.read; + } + + + /** + * 更新opinion + */ + public void updateOpinion(Opinion opinion) { + this.opinion = opinion; + this.updateTime = System.currentTimeMillis(); + } + + /** + * 提交状态校验 + * 是否可以提交 + */ + public void submitStateVerify() { + if (flowStatus == FlowStatus.FINISH) { + throw new IllegalArgumentException("flow is finish"); + } + if (flowType == FlowType.DONE) { + throw new IllegalArgumentException("flow is done"); + } + } + + /** + * 提交流程 + * + * @param flowOperator 操作者 + * @param snapshot 绑定数据 + * @param opinion 意见 + * @param flowSourceDirection 流转方式 + */ + public void submitRecord(IFlowOperator flowOperator, BindDataSnapshot snapshot, Opinion opinion, FlowSourceDirection flowSourceDirection) { + if (!flowOperator.isFlowManager()) { + if (flowOperator.getUserId() != this.currentOperator.getUserId()) { + throw new IllegalArgumentException("current operator is not match"); + } + } else { + this.interferedOperator = this.currentOperator; + this.currentOperator = flowOperator; + this.interfere = true; + } + this.read(); + this.flowSourceDirection = flowSourceDirection; + this.flowType = FlowType.DONE; + this.updateTime = System.currentTimeMillis(); + this.snapshotId = snapshot.getId(); + this.bindClass = snapshot.getClazzName(); + this.opinion = opinion; + } + + /** + * 转交流程 + */ + public void transfer(IFlowOperator flowOperator, BindDataSnapshot snapshot, Opinion opinion) { + if (flowOperator.getUserId() != this.currentOperator.getUserId()) { + throw new IllegalArgumentException("current operator is not match"); + } + this.read(); + this.flowSourceDirection = FlowSourceDirection.TRANSFER; + this.flowType = FlowType.TRANSFER; + this.updateTime = System.currentTimeMillis(); + this.snapshotId = snapshot.getId(); + this.bindClass = snapshot.getClazzName(); + this.opinion = opinion; + } + + + /** + * 转办产生的流程记录 + * + * @param title 标题 + * @param operator 操作者 + */ + public void transferToTodo(String title, IFlowOperator operator) { + this.id = 0; + this.flowType = FlowType.TODO; + this.flowStatus = FlowStatus.RUNNING; + this.postponedCount = 0; + this.updateTime = 0; + this.readTime = 0; + this.read = false; + this.title = title; + this.opinion = null; + this.flowSourceDirection = null; + this.interfere = false; + this.interferedOperator = null; + this.currentOperator = operator; + } + + /** + * 自动提交流程 (非会签时自通审批) + * + * @param flowOperator 操作者 + * @param snapshot 绑定数据 + */ + public void autoPass(IFlowOperator flowOperator, BindDataSnapshot snapshot) { + this.read(); + this.flowSourceDirection = FlowSourceDirection.PASS; + this.currentOperator = flowOperator; + this.flowType = FlowType.DONE; + this.updateTime = System.currentTimeMillis(); + this.snapshotId = snapshot.getId(); + this.bindClass = snapshot.getClazzName(); + this.opinion = Opinion.unSignAutoSuccess(); + } + + + /** + * 完成流程 + */ + public void finish() { + this.flowStatus = FlowStatus.FINISH; + this.finishTime = System.currentTimeMillis(); + } + + + /** + * 是否已审批 + */ + public boolean isDone() { + return this.flowType == FlowType.DONE; + } + + /** + * 是否完成 + */ + public boolean isFinish() { + return this.flowStatus == FlowStatus.FINISH; + } + + /** + * 是否是待办 + */ + public boolean isTodo() { + return this.flowType == FlowType.TODO && this.flowStatus == FlowStatus.RUNNING; + } + + /** + * 是否是转交 + * + * @return 是否是转交 + */ + public boolean isTransfer() { + return this.flowType == FlowType.TRANSFER; + } + + /** + * 审批通过 + */ + public boolean isPass() { + return this.opinion != null && this.opinion.isSuccess() && isDone(); + } + + /** + * 匹配操作者 + * + * @param currentOperator 当前操作者 + */ + public void matcherOperator(IFlowOperator currentOperator) { + if (!isOperator(currentOperator)) { + throw new IllegalArgumentException("current operator is not match"); + } + } + + /** + * 是否是当前操作者 + * + * @param operator 操作者 + * @return 是否是当前操作者 + */ + public boolean isOperator(IFlowOperator operator) { + return this.currentOperator.getUserId() == operator.getUserId(); + } + + + /** + * 撤回流程 + */ + public void recall() { + this.flowType = FlowType.TODO; + this.updateTime = System.currentTimeMillis(); + } + + + /** + * 复制流程记录 + */ + public FlowRecord copy() { + FlowRecord record = new FlowRecord(); + record.setId(this.id); + record.setPostponedCount(this.postponedCount); + record.setPreId(this.preId); + record.setWorkId(this.workId); + record.setProcessId(this.processId); + record.setNodeCode(this.nodeCode); + record.setTitle(this.title); + record.setCurrentOperator(this.currentOperator); + record.setFlowType(this.flowType); + record.setFlowSourceDirection(this.flowSourceDirection); + record.setCreateTime(this.createTime); + record.setUpdateTime(this.updateTime); + record.setFinishTime(this.finishTime); + record.setTimeoutTime(this.timeoutTime); + record.setCreateOperator(this.createOperator); + record.setOpinion(this.opinion); + record.setFlowStatus(this.flowStatus); + record.setErrMessage(this.errMessage); + record.setBindClass(this.bindClass); + record.setSnapshotId(this.snapshotId); + record.setRead(this.read); + record.setInterfere(this.interfere); + record.setInterferedOperator(this.interferedOperator); + record.setReadTime(this.readTime); + return record; + } + + + /** + * 是否超时 + */ + public boolean isTimeout() { + if (this.timeoutTime == 0) { + return false; + } + return System.currentTimeMillis() > this.timeoutTime; + } + + /** + * 是否延期 + */ + public boolean isPostponed() { + return this.postponedCount > 0; + } + + /** + * 是否是发起节点 + */ + public boolean isStartRecord() { + return this.preId == 0; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowBackupRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowBackupRepository.java new file mode 100644 index 00000000..5263f035 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowBackupRepository.java @@ -0,0 +1,33 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.record.FlowBackup; + +/** + * 流程备份仓库(流程快照仓库) + */ +public interface FlowBackupRepository { + + /** + * 备份流程 + * @param flowWork 流程 + * @return 备份对象 + */ + FlowBackup backup(FlowWork flowWork); + + /** + * 根据流程id和版本号获取备份 + * @param workId 流程id + * @param workVersion 版本号 + * @return 备份对象 + */ + FlowBackup getFlowBackupByWorkIdAndVersion(long workId,long workVersion); + + /** + * 根据备份id获取备份 + * @param backupId 备份id + * @return 备份对象 + */ + FlowBackup getFlowBackupById(long backupId); + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowBindDataRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowBindDataRepository.java new file mode 100644 index 00000000..a56cb2c3 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowBindDataRepository.java @@ -0,0 +1,31 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; + +/** + * 流程绑定数据仓库 + * 流程绑定数据即,流程的表单数据 + */ +public interface FlowBindDataRepository { + + /** + * 保存数据 + * @param snapshot 数据 + */ + void save(BindDataSnapshot snapshot); + + /** + * 更新数据 + * @param snapshot 数据 + */ + void update(BindDataSnapshot snapshot); + + + /** + * 查询快照数据 + * @param id 快照id + * @return BindDataSnapshot + */ + BindDataSnapshot getBindDataSnapshotById(long id); + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowOperatorRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowOperatorRepository.java new file mode 100644 index 00000000..4f73f7d9 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowOperatorRepository.java @@ -0,0 +1,29 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.user.IFlowOperator; + +import java.util.List; + +/** + * 流程操作者 仓库 + */ +public interface FlowOperatorRepository { + + /** + * 根据ID查询流程用户 + * + * @param ids IDs + * @return List of IFlowOperator + */ + List findByIds(List ids); + + + /** + * 根据ID查询流程用户 + * + * @param id ID + * @return IFlowOperator + */ + IFlowOperator getFlowOperatorById(long id); + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java new file mode 100644 index 00000000..568d35b5 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java @@ -0,0 +1,16 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.record.FlowProcess; +import com.codingapi.springboot.flow.domain.FlowWork; + +/** + * 流程仓库,每一个流程都会在创建时被创建一条process数据,用于标识流程 + */ +public interface FlowProcessRepository { + + void save(FlowProcess flowProcess); + + + FlowWork getFlowWorkByProcessId(String processId); + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java new file mode 100644 index 00000000..623c420d --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java @@ -0,0 +1,70 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.record.FlowRecord; + +import java.util.List; + + +/** + * 流转记录数据仓库 + */ +public interface FlowRecordRepository { + + /** + * 保存流程记录 + * + * @param records 流程记录 + */ + void save(List records); + + /** + * 更新流程记录 + * + * @param flowRecord 流程记录 + */ + void update(FlowRecord flowRecord); + + /** + * 根据ID查询流程记录 + * + * @param id 流程记录ID + * @return FlowRecord + */ + FlowRecord getFlowRecordById(long id); + + /** + * 根据前置ID查询流程记录 + * + * @param preId 前置ID + * @return List of FlowRecord + */ + List findFlowRecordByPreId(long preId); + + + /** + * 根据流程id查询流程记录 + * @param processId 流程id + */ + List findFlowRecordByProcessId(String processId); + + + /** + * 查询所有未完成的流程记录 + * @param processId 流程id + * @return List of FlowRecord + */ + List findTodoFlowRecordByProcessId(String processId); + + /** + * 根据流程id 修改所有的记录状态为已完成 + * + * @param processId 流程id + */ + void finishFlowRecordByProcessId(String processId); + + /** + * 删除流程记录 + * @param childrenRecords 流程记录 + */ + void delete(List childrenRecords); +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowWorkRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowWorkRepository.java new file mode 100644 index 00000000..093e918e --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowWorkRepository.java @@ -0,0 +1,18 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.domain.FlowWork; + +/** + * 流程设计器仓库 + */ +public interface FlowWorkRepository { + + FlowWork getFlowWorkById(long id); + + FlowWork getFlowWorkByCode(String code); + + void save(FlowWork flowWork); + + void delete(long id); + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/script/GroovyShellContext.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/script/GroovyShellContext.java new file mode 100644 index 00000000..356fbb6e --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/script/GroovyShellContext.java @@ -0,0 +1,87 @@ +package com.codingapi.springboot.flow.script; + +import com.codingapi.springboot.flow.utils.Sha256Utils; +import groovy.lang.GroovyShell; +import groovy.lang.Script; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class GroovyShellContext { + + @Getter + private final static GroovyShellContext instance = new GroovyShellContext(); + + private final static GroovyShell groovyShell = new GroovyShell(); + + private final Map cache = new HashMap<>(); + + private final static ExecutorService threadPool = Executors.newFixedThreadPool(10); + + // 缓存最大值 + private final static int MAX_CACHE_SIZE = 10000; + + + private GroovyShellContext() { + } + + public ShellScript parse(String script) { + String hash = Sha256Utils.generateSHA256(script); + if (cache.containsKey(hash)) { + return cache.get(hash); + } else { + if (cache.size() > MAX_CACHE_SIZE) { + cache.clear(); + } + ShellScript shellScript = new ShellScript(script); + threadPool.submit(shellScript); + cache.put(hash, shellScript); + return shellScript; + } + } + + + public int size() { + return cache.size(); + } + + public static class ShellScript implements Runnable { + + @Getter + private final String script; + + private Script runtime; + + public ShellScript(String script) { + this.script = script; + } + + public Object invokeMethod(String run, Object params) { + synchronized (ShellScript.this) { + if (runtime == null) { + try { + ShellScript.this.wait(1000); + } catch (InterruptedException ignored) { + } + if (runtime == null) { + runtime = groovyShell.parse(script); + } + } + return runtime.invokeMethod(run, params); + } + } + + @Override + public void run() { + runtime = groovyShell.parse(script); + synchronized (ShellScript.this) { + this.notifyAll(); + } + } + } + + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java new file mode 100644 index 00000000..5e22c61e --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java @@ -0,0 +1,94 @@ +package com.codingapi.springboot.flow.serializable; + +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.em.NodeType; +import com.codingapi.springboot.flow.error.ErrTrigger; +import com.codingapi.springboot.flow.generator.TitleGenerator; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; + +/** + * 流程节点序列化 + */ +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class FlowNodeSerializable implements Serializable { + + /** + * 节点id + */ + private String id; + + /** + * 节点编码 + */ + private String code; + + /** + * 节点名称 + */ + private String name; + + /** + * 节点标题创建规则 + */ + private String titleGenerator; + + /** + * 节点类型 | 分为发起、审批、结束 + */ + private NodeType type; + + /** + * 节点视图 + */ + private String view; + + /** + * 流程审批类型 | 分为会签、非会签 + */ + private ApprovalType approvalType; + + /** + * 操作者匹配器 + */ + private String operatorMatcher; + + /** + * 是否可编辑 + */ + private boolean editable; + + /** + * 创建时间 + */ + private long createTime; + /** + * 更新时间 + */ + private long updateTime; + + /** + * 超时时间(毫秒) + */ + private long timeout; + + /** + * 异常触发器,当流程发生异常时异常通常是指找不到审批人,将会触发异常触发器,异常触发器可以是一个节点 + */ + private String errTrigger; + + + public FlowNode toFlowNode() { + return new FlowNode(id, code, name, new TitleGenerator(titleGenerator), type, view, approvalType, + new OperatorMatcher(operatorMatcher), editable, createTime, updateTime, timeout, errTrigger == null ? null : new ErrTrigger(errTrigger)); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowRelationSerializable.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowRelationSerializable.java new file mode 100644 index 00000000..d2e0e0aa --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowRelationSerializable.java @@ -0,0 +1,82 @@ +package com.codingapi.springboot.flow.serializable; + +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowRelation; +import com.codingapi.springboot.flow.trigger.OutTrigger; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * 流程关系序列化 + */ +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class FlowRelationSerializable implements Serializable { + + /** + * 关系id + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 源节点 + */ + private String sourceId; + + /** + * 目标节点 + */ + private String targetId; + + /** + * 排序 + */ + private int order; + + /** + * 是否退回 + */ + private boolean back; + + /** + * 出口触发器 + */ + private String outTrigger; + + + /** + * 创建时间 + */ + private long createTime; + + /** + * 修改时间 + */ + private long updateTime; + + public FlowRelation toFlowRelation(List nodes) { + FlowNode source = null; + FlowNode target = null; + for (FlowNode node : nodes) { + if (node.getId().equals(sourceId)) { + source = node; + } + if (node.getId().equals(targetId)) { + target = node; + } + } + return new FlowRelation(id, name, source, target, order, back, new OutTrigger(outTrigger), createTime, updateTime); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java new file mode 100644 index 00000000..050561a1 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java @@ -0,0 +1,140 @@ +package com.codingapi.springboot.flow.serializable; + +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.em.NodeType; +import com.codingapi.springboot.flow.repository.FlowOperatorRepository; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.ByteArrayOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 流程序列化 + * 流程序列化为了减少数据存储的压力,该数据会存储到FlowProcess的创建过程中,为了降低数据的存储容量,将会自动判断 + * 是否存在相同的版本,若存在时则不会存储新的数据。 + * + */ +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class FlowWorkSerializable implements Serializable { + + /** + * 流程的设计id + */ + private long id; + + /** + * 流程编号 + */ + private String code; + + /** + * 流程标题 + */ + private String title; + /** + * 流程描述 + */ + private String description; + /** + * 流程创建者 + */ + private long createUser; + /** + * 创建时间 + */ + private long createTime; + /** + * 更新时间 + */ + private long updateTime; + /** + * 是否启用 + */ + @Setter + private boolean enable; + + /** + * 最大延期次数 + */ + @Setter + private int postponedMax; + + /** + * 流程的节点(发起节点) + */ + private List nodes; + + /** + * 流程的关系 + */ + private List relations; + + + /** + * 序列化 + * + * @return 序列化对象 + */ + public byte[] toSerializable() { + Kryo kryo = new Kryo(); + kryo.register(ArrayList.class); + kryo.register(FlowNodeSerializable.class); + kryo.register(FlowRelationSerializable.class); + kryo.register(FlowWorkSerializable.class); + kryo.register(ApprovalType.class); + kryo.register(NodeType.class); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + Output output = new Output(outputStream); + kryo.writeObject(output, this); + output.close(); + return outputStream.toByteArray(); + } + + + public static FlowWorkSerializable fromSerializable(byte[] bytes) { + Kryo kryo = new Kryo(); + kryo.register(ArrayList.class); + kryo.register(FlowNodeSerializable.class); + kryo.register(FlowRelationSerializable.class); + kryo.register(FlowWorkSerializable.class); + kryo.register(ApprovalType.class); + kryo.register(NodeType.class); + return kryo.readObject(new Input(bytes), FlowWorkSerializable.class); + } + + + public FlowWork toFlowWork(FlowOperatorRepository flowOperatorRepository) { + List flowNodes = nodes.stream().map(FlowNodeSerializable::toFlowNode).collect(Collectors.toList()); + return new FlowWork( + id, + code, + title, + description, + flowOperatorRepository.getFlowOperatorById(createUser), + createTime, + updateTime, + enable, + postponedMax, + flowNodes, + relations.stream().map((item) -> item.toFlowRelation(flowNodes)).collect(Collectors.toList()), + null + ); + } + + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java new file mode 100644 index 00000000..2326a8fd --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java @@ -0,0 +1,126 @@ +package com.codingapi.springboot.flow.service; + +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.FlowSourceDirection; +import com.codingapi.springboot.flow.record.FlowRecord; +import lombok.Getter; + +import java.util.List; + +/** + * 流程方向服务 + */ +class FlowDirectionService { + + private final FlowWork flowWork; + private final FlowNode flowNode; + private final Opinion opinion; + + @Getter + private FlowSourceDirection flowSourceDirection; + + + private List historyRecords; + + public FlowDirectionService(FlowNode flowNode, FlowWork flowWork, Opinion opinion) { + this.flowNode = flowNode; + this.opinion = opinion; + this.flowWork = flowWork; + } + + + public void bindHistoryRecords(List historyRecords) { + this.historyRecords = historyRecords; + } + + + /** + * 解析当前的审批方向 + */ + public void loadFlowSourceDirection() { + if (opinion.isSuccess()) { + flowSourceDirection = FlowSourceDirection.PASS; + } + if (opinion.isReject()) { + flowSourceDirection = FlowSourceDirection.REJECT; + } + } + + + /** + * 重新加载审批方向 + * 根据会签结果判断是否需要重新设置审批方向 + */ + public FlowSourceDirection reloadFlowSourceDirection() { + if (flowNode.isSign()) { + boolean allPass = historyRecords.stream().filter(item -> !item.isTransfer()).allMatch(FlowRecord::isPass); + if (!allPass) { + flowSourceDirection = FlowSourceDirection.REJECT; + } + } + return flowSourceDirection; + } + + + /** + * 校验流程的审批方向 + */ + public void verifyFlowSourceDirection() { + if (flowSourceDirection == null) { + throw new IllegalArgumentException("flow source direction is null"); + } + if (flowNode.isStartNode() && flowSourceDirection == FlowSourceDirection.REJECT) { + throw new IllegalArgumentException("flow node is start node"); + } + } + + /** + * 判断当前流程节点是否已经完成,是否可以继续流转 + */ + public boolean hasCurrentFlowNodeIsDone() { + // 会签下所有人尚未提交时,不执行下一节点 + boolean allDone = historyRecords.stream().filter(item -> !item.isTransfer()).allMatch(FlowRecord::isDone); + if (!allDone) { + // 流程尚未审批结束直接退出 + return true; + } + return false; + } + + + /** + * 检测当前流程是否已经完成 + * 即流程已经进行到了最终节点且审批意见为同意 + */ + public boolean hasCurrentFlowIsFinish() { + if (flowSourceDirection == FlowSourceDirection.PASS && flowNode.isOverNode()) { + return true; + } + return false; + } + + + /** + * 判断当前流程是否为默认的驳回流程 + */ + public boolean isDefaultBackRecord() { + return flowSourceDirection == FlowSourceDirection.REJECT && !flowWork.hasBackRelation(); + } + + /** + * 判断当前流程是否为通过流程 + */ + public boolean isPassBackRecord() { + return flowSourceDirection == FlowSourceDirection.PASS; + } + + /** + * 判断当前流程是否为自定义的驳回流程 + */ + public boolean isCustomBackRecord() { + return flowSourceDirection == FlowSourceDirection.REJECT && flowWork.hasBackRelation(); + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordBuilderService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordBuilderService.java new file mode 100644 index 00000000..654ef87a --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordBuilderService.java @@ -0,0 +1,251 @@ +package com.codingapi.springboot.flow.service; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowRelation; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.error.ErrorResult; +import com.codingapi.springboot.flow.error.NodeResult; +import com.codingapi.springboot.flow.error.OperatorResult; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowOperatorRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.user.IFlowOperator; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 流程记录构建服务 + */ +class FlowRecordBuilderService { + + + private final FlowOperatorRepository flowOperatorRepository; + private final FlowRecordRepository flowRecordRepository; + + private final String processId; + private final long preId; + + private final FlowWork flowWork; + private final Opinion opinion; + private final IFlowOperator currentOperator; + private final BindDataSnapshot snapshot; + private final List historyRecords; + private final IFlowOperator createOperator; + + + public FlowRecordBuilderService(FlowOperatorRepository flowOperatorRepository, + FlowRecordRepository flowRecordRepository, + BindDataSnapshot snapshot, + Opinion opinion, + IFlowOperator createOperator, + IFlowOperator currentOperator, + List historyRecords, + FlowWork flowWork, + String processId, + long preId) { + + if(createOperator==null){ + throw new IllegalArgumentException("createOperator is null"); + } + + this.createOperator = createOperator; + this.flowOperatorRepository = flowOperatorRepository; + + this.flowRecordRepository = flowRecordRepository; + this.snapshot = snapshot; + this.opinion = opinion; + this.currentOperator = currentOperator; + this.flowWork = flowWork; + + + this.processId = processId; + this.preId = preId; + this.historyRecords = historyRecords; + } + + + /** + * 获取下一个节点 + * + * @return 下一个节点 + */ + private FlowNode matcherNextNode(FlowNode flowNode, boolean back) { + List relations = flowWork.getRelations().stream() + .filter(relation -> relation.sourceMatcher(flowNode.getCode())) + .filter(relation -> relation.isBack() == back) + .sorted((o1, o2) -> (o2.getOrder() - o1.getOrder())) + .collect(Collectors.toList()); + if (relations.isEmpty()) { + throw new IllegalArgumentException("relation not found"); + } + FlowSession flowSession = new FlowSession(flowWork, flowNode, createOperator, currentOperator, snapshot.toBindData(), opinion, historyRecords); + List flowNodes = new ArrayList<>(); + for (FlowRelation flowRelation : relations) { + FlowNode node = flowRelation.trigger(flowSession); + if (node != null) { + flowNodes.add(node); + } + } + if (flowNodes.isEmpty()) { + throw new IllegalArgumentException("next node not found"); + } + return flowNodes.get(0); + } + + /** + * 异常匹配 + * + * @param currentNode 当前节点 + * @param currentOperator 当前操作者 + * @return 流程记录 + */ + private List errMatcher(FlowNode currentNode, IFlowOperator currentOperator) { + if (currentNode.hasErrTrigger()) { + FlowSession flowSession = new FlowSession(flowWork, currentNode, createOperator, currentOperator, snapshot.toBindData(), opinion, historyRecords); + ErrorResult errorResult = currentNode.errMatcher(flowSession); + if (errorResult == null) { + throw new IllegalArgumentException("errMatcher match error."); + } + + // 匹配操作者 + if (errorResult.isOperator()) { + List recordList = new ArrayList<>(); + List operatorIds = ((OperatorResult) errorResult).getOperatorIds(); + List operators = flowOperatorRepository.findByIds(operatorIds); + for (IFlowOperator operator : operators) { + FlowSession content = new FlowSession(flowWork, currentNode, createOperator, operator, snapshot.toBindData(), opinion, historyRecords); + String recordTitle = currentNode.generateTitle(content); + FlowRecord record = currentNode.createRecord(flowWork.getId(), processId, preId, recordTitle, createOperator, operator, snapshot); + recordList.add(record); + } + return recordList; + } + // 匹配节点 + if (errorResult.isNode()) { + String nodeCode = ((NodeResult) errorResult).getNode(); + FlowNode node = flowWork.getNodeByCode(nodeCode); + if (node == null) { + throw new IllegalArgumentException("node not found."); + } + List recordList = new ArrayList<>(); + FlowSession content = new FlowSession(flowWork, node, createOperator, currentOperator, snapshot.toBindData(), opinion, historyRecords); + List matcherOperators = node.loadFlowNodeOperator(content, flowOperatorRepository); + if (!matcherOperators.isEmpty()) { + for (IFlowOperator matcherOperator : matcherOperators) { + String recordTitle = node.generateTitle(content); + FlowRecord record = node.createRecord(flowWork.getId(), processId, preId, recordTitle, createOperator, matcherOperator, snapshot); + recordList.add(record); + } + } + return recordList; + } + throw new IllegalArgumentException("errMatcher not match."); + } + throw new IllegalArgumentException("operator not match."); + } + + + /** + * 创建流程记录 + * + * @param currentNode 当前节点 + * @return 流程记录 + */ + public List createRecord(FlowNode currentNode, IFlowOperator currentOperator) { + return this.createRecord(currentNode,currentOperator,null); + } + + /** + * 创建流程记录 + * + * @param currentNode 当前节点 + * @param currentOperator 当前审批人 + * @param opinion 审批意见 + * @return 流程记录 + */ + public List createRecord(FlowNode currentNode, IFlowOperator currentOperator,Opinion opinion) { + FlowSession flowSession = new FlowSession(flowWork, currentNode, createOperator, currentOperator, snapshot.toBindData(), opinion, historyRecords); + long workId = flowWork.getId(); + List operators = currentNode.loadFlowNodeOperator(flowSession, flowOperatorRepository); + List recordList; + if (operators.isEmpty()) { + recordList= this.errMatcher(currentNode, currentOperator); + if (recordList.isEmpty()) { + throw new IllegalArgumentException("operator not match."); + } + } else { + String recordTitle = currentNode.generateTitle(flowSession); + recordList = new ArrayList<>(); + for (IFlowOperator operator : operators) { + FlowRecord record = currentNode.createRecord(workId, processId, preId, recordTitle, createOperator, operator, snapshot); + recordList.add(record); + } + } + if(!recordList.isEmpty()){ + for (FlowRecord record:recordList){ + if(opinion!=null){ + record.updateOpinion(opinion); + } + } + } + + return recordList; + } + + + /** + * 创建下一个节点 + */ + public List createNextRecord(FlowNode flowNode) { + FlowNode nextNode = this.matcherNextNode(flowNode, false); + return this.createRecord(nextNode, currentOperator); + } + + /** + * 创建自定义的下级别节点 + */ + public List createCustomBackRecord(FlowNode flowNode, long parentRecordId) { + FlowNode nextNode = this.matcherNextNode(flowNode, true); + if (nextNode == null) { + throw new IllegalArgumentException("next node not found"); + } + IFlowOperator flowOperator = currentOperator; + if (nextNode.isAnyOperatorMatcher()) { + // 如果是任意人员操作时则需要指定为当时审批人员为当前审批人员 + FlowRecord preFlowRecord = flowRecordRepository.getFlowRecordById(parentRecordId); + while (preFlowRecord.isTransfer() || !preFlowRecord.getNodeCode().equals(nextNode.getCode())) { + preFlowRecord = flowRecordRepository.getFlowRecordById(preFlowRecord.getPreId()); + } + flowOperator = preFlowRecord.getCurrentOperator(); + } + return this.createRecord(nextNode, flowOperator); + } + + /** + * 创建默认拒绝时的流程记录 + */ + public List createDefaultBackRecord(long parentRecordId) { + IFlowOperator flowOperator; + // 拒绝时,默认返回上一个节点 + FlowRecord preRecord = flowRecordRepository.getFlowRecordById(parentRecordId); + // 去除所有的转办的记录 + while (preRecord.isTransfer()) { + // 继续寻找上一个节点 + preRecord = flowRecordRepository.getFlowRecordById(preRecord.getPreId()); + } + // 获取上一个节点的审批者,继续将审批者设置为当前审批者 + flowOperator = preRecord.getCurrentOperator(); + FlowNode nextNode = flowWork.getNodeByCode(preRecord.getNodeCode()); + if (nextNode == null) { + throw new IllegalArgumentException("next node not found"); + } + return this.createRecord(nextNode, flowOperator); + } + + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordService.java new file mode 100644 index 00000000..910529bb --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordService.java @@ -0,0 +1,192 @@ +package com.codingapi.springboot.flow.service; + +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.Getter; + +import java.util.List; + +/** + * 流程记录服务(流程内部服务) + */ +class FlowRecordService { + + // constructor params + private final long recordId; + @Getter + private final IFlowOperator currentOperator; + + // register repository + final FlowRecordRepository flowRecordRepository; + final FlowProcessRepository flowProcessRepository; + + // load Object + @Getter + private FlowWork flowWork; + @Getter + private FlowNode flowNode; + @Getter + private FlowRecord flowRecord; + + public FlowRecordService(FlowRecordRepository flowRecordRepository, + FlowProcessRepository flowProcessRepository, + long recordId, + IFlowOperator currentOperator) { + this.flowRecordRepository = flowRecordRepository; + this.flowProcessRepository = flowProcessRepository; + + this.currentOperator = currentOperator; + this.recordId = recordId; + } + + + + /** + * 校验流程记录是否已提交状态 + */ + public void verifyFlowRecordSubmitState() { + flowRecord.submitStateVerify(); + } + + /** + * 校验流程是否当前操作者可操作的 + */ + public void verifyFlowRecordCurrentOperator() { + if(!currentOperator.isFlowManager()) { + flowRecord.matcherOperator(currentOperator); + } + } + + /** + * 校验流程是否已审批 + */ + public void verifyFlowRecordNotDone() { + if (flowRecord.isDone()) { + throw new IllegalArgumentException("flow record is done"); + } + } + + + /** + * 校验流程是否已审批 + */ + public void verifyFlowRecordIsDone() { + if (!flowRecord.isDone()) { + throw new IllegalArgumentException("flow record is not done"); + } + } + + + + /** + * 校验流程是否未审批 + */ + public void verifyFlowRecordNotTodo() { + if (flowRecord.isTodo()) { + throw new IllegalArgumentException("flow record is todo"); + } + } + + /** + * 校验流程是未审批 + */ + public void verifyFlowRecordIsTodo() { + if (!flowRecord.isTodo()) { + throw new IllegalArgumentException("flow record is not todo"); + } + } + + /** + * 校验流程是否已完成 + */ + public void verifyFlowRecordNotFinish() { + if (flowRecord.isFinish()) { + throw new IllegalArgumentException("flow record is finish"); + } + } + + /** + * 校验流程节点是否可编辑 + */ + public void verifyFlowNodeEditableState(boolean editable) { + // 流程节点不可编辑时,不能保存 + if (flowNode.isEditable() == editable) { + throw new IllegalArgumentException("flow node is not editable"); + } + } + + + /** + * 校验转办人员不能是当前操作者 + */ + public void verifyTargetOperatorIsNotCurrentOperator(IFlowOperator targetOperator) { + if(currentOperator.getUserId() == targetOperator.getUserId()){ + throw new IllegalArgumentException("current operator is target operator"); + } + } + + + /** + * 获取流程记录对象 + */ + public void loadFlowRecord() { + FlowRecord flowRecord = flowRecordRepository.getFlowRecordById(recordId); + if (flowRecord == null) { + throw new IllegalArgumentException("flow record not found"); + } + this.flowRecord = flowRecord; + } + + /** + * 获取流程设计对象 + */ + public void loadFlowWork() { + FlowWork flowWork = flowProcessRepository.getFlowWorkByProcessId(flowRecord.getProcessId()); + if (flowWork == null) { + throw new IllegalArgumentException("flow work not found"); + } + flowWork.enableValidate(); + this.flowWork = flowWork; + } + + + /** + * 获取流程节点对象 + */ + public void loadFlowNode() { + FlowNode flowNode = flowWork.getNodeByCode(flowRecord.getNodeCode()); + if (flowNode == null) { + throw new IllegalArgumentException("flow node not found"); + } + this.flowNode = flowNode; + } + + /** + * 标记流程为已读状态 + */ + public void setFlowRecordRead() { + if (currentOperator != null) { + if(flowRecord.isOperator(currentOperator)) { + if (!flowRecord.isRead()) { + flowRecord.read(); + flowRecordRepository.update(flowRecord); + } + } + } + } + + /** + * 校验是否后续没有审批记录 + */ + public void verifyChildrenRecordsIsEmpty() { + List childrenRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getId()); + if (!childrenRecords.isEmpty()) { + throw new IllegalArgumentException("flow node is done"); + } + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java new file mode 100644 index 00000000..25309652 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -0,0 +1,522 @@ +package com.codingapi.springboot.flow.service; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.FlowSourceDirection; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.pojo.FlowResult; +import com.codingapi.springboot.flow.record.FlowBackup; +import com.codingapi.springboot.flow.record.FlowProcess; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + + +/** + * 流程服务 + */ +@Transactional +@AllArgsConstructor +public class FlowService { + + + private final FlowWorkRepository flowWorkRepository; + private final FlowRecordRepository flowRecordRepository; + private final FlowBindDataRepository flowBindDataRepository; + private final FlowOperatorRepository flowOperatorRepository; + private final FlowProcessRepository flowProcessRepository; + private final FlowBackupRepository flowBackupRepository; + + + /** + * 流程详情 + * + * @param recordId 流程记录id + * @return 流程详情 + */ + public FlowDetail detail(long recordId) { + return detail(recordId, null); + } + + /** + * 延期待办 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param time 延期时间 + */ + public void postponed(long recordId, IFlowOperator currentOperator, long time) { + FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + flowRecordService.loadFlowRecord(); + flowRecordService.verifyFlowRecordSubmitState(); + flowRecordService.verifyFlowRecordCurrentOperator(); + flowRecordService.loadFlowWork(); + flowRecordService.verifyFlowRecordNotFinish(); + flowRecordService.verifyFlowRecordNotDone(); + + FlowRecord flowRecord = flowRecordService.getFlowRecord(); + FlowWork flowWork = flowRecordService.getFlowWork(); + + flowRecord.postponedTime(flowWork.getPostponedMax(), time); + flowRecordRepository.update(flowRecord); + } + + /** + * 催办流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public void urge(long recordId, IFlowOperator currentOperator) { + FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + flowRecordService.loadFlowRecord(); + flowRecordService.loadFlowWork(); + flowRecordService.verifyFlowRecordIsDone(); + + FlowRecord flowRecord = flowRecordService.getFlowRecord(); + FlowWork flowWork = flowRecordService.getFlowWork(); + + List todoRecords = flowRecordRepository.findTodoFlowRecordByProcessId(flowRecord.getProcessId()); + + // 推送催办消息 + for (FlowRecord record : todoRecords) { + IFlowOperator pushOperator = record.getCurrentOperator(); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_URGE, record, pushOperator, flowWork, null)); + } + + } + + /** + * 流程详情 + * 如果传递了currentOperator为流程的审批者时,在查看详情的时候可以将流程记录标记为已读 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public FlowDetail detail(long recordId, IFlowOperator currentOperator) { + + FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + flowRecordService.loadFlowRecord(); + flowRecordService.setFlowRecordRead(); + flowRecordService.loadFlowWork(); + + FlowRecord flowRecord = flowRecordService.getFlowRecord(); + FlowWork flowWork = flowRecordService.getFlowWork(); + + + BindDataSnapshot snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + List flowRecords = + flowRecordRepository.findFlowRecordByProcessId(flowRecord.getProcessId()). + stream(). + sorted((o1, o2) -> (int) (o2.getId() - o1.getId())) + .collect(Collectors.toList()); + + List operators = new ArrayList<>(); + // 获取所有的操作者 + for (FlowRecord record : flowRecords) { + operators.add(record.getCreateOperator()); + operators.add(record.getCurrentOperator()); + operators.add(record.getInterferedOperator()); + } + + return new FlowDetail(flowRecord, snapshot, flowWork, flowRecords, operators); + } + + + /** + * 干预流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public FlowResult interfere(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + if (!currentOperator.isFlowManager()) { + throw new IllegalArgumentException("current operator is not flow manager"); + } + return this.submitFlow(recordId, currentOperator, bindData, opinion); + } + + + /** + * 转办流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param targetOperator 转办操作者 + * @param bindData 绑定数据 + * @param advice 转办意见 + */ + public void transfer(long recordId, IFlowOperator currentOperator, IFlowOperator targetOperator, IBindData bindData, String advice) { + + FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + flowRecordService.loadFlowRecord(); + flowRecordService.verifyFlowRecordSubmitState(); + flowRecordService.verifyFlowRecordCurrentOperator(); + flowRecordService.verifyTargetOperatorIsNotCurrentOperator(targetOperator); + + flowRecordService.loadFlowWork(); + flowRecordService.loadFlowNode(); + + flowRecordService.verifyFlowRecordIsTodo(); + + FlowRecord flowRecord = flowRecordService.getFlowRecord(); + FlowWork flowWork = flowRecordService.getFlowWork(); + FlowNode flowNode = flowRecordService.getFlowNode(); + + + // 保存绑定数据 + BindDataSnapshot snapshot = new BindDataSnapshot(bindData); + flowBindDataRepository.save(snapshot); + + // 构建审批意见 + Opinion opinion = Opinion.transfer(advice); + + // 设置自己的流程状态为转办已完成 + flowRecord.transfer(currentOperator, snapshot, opinion); + flowRecordRepository.update(flowRecord); + + // 获取创建者 + IFlowOperator createOperator = flowRecord.getCreateOperator(); + + // 与当前流程同级的流程记录 + List historyRecords; + if (flowRecord.isStartRecord()) { + historyRecords = new ArrayList<>(); + } else { + historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()); + } + + // 创建新的待办标题 + FlowSession content = new FlowSession(flowWork, flowNode, createOperator, targetOperator, snapshot.toBindData(), opinion, historyRecords); + String generateTitle = flowNode.generateTitle(content); + + // 创建转办记录 + FlowRecord transferRecord = flowRecord.copy(); + transferRecord.transferToTodo(generateTitle, targetOperator); + flowRecordRepository.save(Collections.singletonList(transferRecord)); + + // 推送转办消息 + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TRANSFER, flowRecord, currentOperator, flowWork, snapshot.toBindData())); + + // 推送待办消息 + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, transferRecord, targetOperator, flowWork, snapshot.toBindData())); + } + + + /** + * 保存流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param advice 审批意见 + */ + public void save(long recordId, IFlowOperator currentOperator, IBindData bindData, String advice) { + FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + flowRecordService.loadFlowRecord(); + flowRecordService.verifyFlowRecordSubmitState(); + flowRecordService.verifyFlowRecordCurrentOperator(); + flowRecordService.loadFlowWork(); + flowRecordService.loadFlowNode(); + flowRecordService.verifyFlowNodeEditableState(false); + + Opinion opinion = Opinion.save(advice); + FlowRecord flowRecord = flowRecordService.getFlowRecord(); + BindDataSnapshot snapshot = new BindDataSnapshot(flowRecord.getSnapshotId(), bindData); + flowBindDataRepository.update(snapshot); + + flowRecord.setOpinion(opinion); + flowRecordService.flowRecordRepository.update(flowRecord); + + } + + + /** + * 发起流程 (不自动提交到下一节点) + * + * @param workCode 流程编码 + * @param operator 操作者 + * @param bindData 绑定数据 + * @param advice 审批意见 + */ + public FlowResult startFlow(String workCode, IFlowOperator operator, IBindData bindData, String advice) { + // 检测流程是否存在 + FlowWork flowWork = flowWorkRepository.getFlowWorkByCode(workCode); + if (flowWork == null) { + throw new IllegalArgumentException("flow work not found"); + } + flowWork.verify(); + flowWork.enableValidate(); + + // 流程数据备份 + FlowBackup flowBackup = flowBackupRepository.getFlowBackupByWorkIdAndVersion(flowWork.getId(), flowWork.getUpdateTime()); + if (flowBackup == null) { + flowBackup = flowBackupRepository.backup(flowWork); + } + + // 保存流程 + FlowProcess flowProcess = new FlowProcess(flowBackup.getId(), operator); + flowProcessRepository.save(flowProcess); + + // 保存绑定数据 + BindDataSnapshot snapshot = new BindDataSnapshot(bindData); + flowBindDataRepository.save(snapshot); + + // 创建流程id + String processId = flowProcess.getProcessId(); + + // 构建审批意见 + Opinion opinion = Opinion.pass(advice); + + // 获取开始节点 + FlowNode start = flowWork.getStartNode(); + if (start == null) { + throw new IllegalArgumentException("start node not found"); + } + // 设置开始流程的上一个流程id + long preId = 0; + + List historyRecords = new ArrayList<>(); + + FlowRecordBuilderService flowRecordBuilderService = new FlowRecordBuilderService( + flowOperatorRepository, + flowRecordRepository, + snapshot, + opinion, + operator, + operator, + historyRecords, + flowWork, + processId, + preId + ); + + // 创建待办记录 + List records = flowRecordBuilderService.createRecord(start, operator, opinion); + if (records.isEmpty()) { + throw new IllegalArgumentException("flow record not found"); + } + // 保存流程记录 + flowRecordRepository.save(records); + + // 推送事件消息 + for (FlowRecord record : records) { + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_CREATE, record, operator, flowWork, snapshot.toBindData())); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, record, operator, flowWork, snapshot.toBindData())); + } + // 当前的审批记录 + return new FlowResult(flowWork, records); + } + + /** + * 提交流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + + FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, flowProcessRepository, recordId, currentOperator); + + // 加载流程 + flowRecordService.loadFlowRecord(); + // 验证流程的提交状态 + flowRecordService.verifyFlowRecordSubmitState(); + // 验证当前操作者 + flowRecordService.verifyFlowRecordCurrentOperator(); + // 加载流程设计 + flowRecordService.loadFlowWork(); + // 加载流程节点 + flowRecordService.loadFlowNode(); + // 验证没有子流程 + flowRecordService.verifyChildrenRecordsIsEmpty(); + + // 获取流程记录对象 + FlowRecord flowRecord = flowRecordService.getFlowRecord(); + FlowNode flowNode = flowRecordService.getFlowNode(); + FlowWork flowWork = flowRecordService.getFlowWork(); + + + // 保存流程表单快照数据 + BindDataSnapshot snapshot = null; + if (flowNode.isEditable()) { + snapshot = new BindDataSnapshot(bindData); + flowBindDataRepository.save(snapshot); + } else { + snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + } + + // 审批方向判断服务 + FlowDirectionService flowDirectionService = new FlowDirectionService(flowRecordService.getFlowNode(), flowRecordService.getFlowWork(), opinion); + + // 加载流程审批方向 + flowDirectionService.loadFlowSourceDirection(); + // 验证审批方向 + flowDirectionService.verifyFlowSourceDirection(); + + // 根据当前方向提交流程 + FlowSourceDirection flowSourceDirection = flowDirectionService.getFlowSourceDirection(); + flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); + flowRecordRepository.update(flowRecord); + + // 与当前流程同级的流程记录 + List historyRecords; + if (flowRecord.isStartRecord()) { + historyRecords = new ArrayList<>(); + } else { + historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()); + } + flowDirectionService.bindHistoryRecords(historyRecords); + + // 判断流程是否结束(会签时需要所有人都通过) + if (flowNode.isSign()) { + boolean next = flowDirectionService.hasCurrentFlowNodeIsDone(); + if (next) { + List todoRecords = historyRecords.stream().filter(FlowRecord::isTodo).collect(Collectors.toList()); + return new FlowResult(flowWork, todoRecords); + } + } + + // 非会签下,当有人提交以后,将所有未提交的流程都自动提交,然后再执行下一节点 + if (flowNode.isUnSign()) { + for (FlowRecord record : historyRecords) { + if (record.isTodo() && record.getId() != flowRecord.getId()) { + record.autoPass(currentOperator, snapshot); + flowRecordRepository.update(flowRecord); + } + } + } + + // 根据所有提交意见,重新加载审批方向 + flowSourceDirection = flowDirectionService.reloadFlowSourceDirection(); + + + // 判断流程是否完成 + if (flowDirectionService.hasCurrentFlowIsFinish()) { + flowRecord.finish(); + flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); + flowRecordRepository.update(flowRecord); + flowRecordRepository.finishFlowRecordByProcessId(flowRecord.getProcessId()); + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_FINISH, flowRecord, currentOperator, flowWork, snapshot.toBindData())); + return new FlowResult(flowWork, flowRecord); + } + + // 获取流程的发起者 + IFlowOperator createOperator = flowRecord.getCreateOperator(); + + // 构建流程创建器 + FlowRecordBuilderService flowRecordBuilderService = new FlowRecordBuilderService( + flowOperatorRepository, + flowRecordRepository, + snapshot, + opinion, + createOperator, + currentOperator, + historyRecords, + flowWork, + flowRecord.getProcessId(), + flowRecord.getId() + ); + + // 创建下一节点的流程记录 + List records; + // 审批通过并进入下一节点 + if (flowDirectionService.isPassBackRecord()) { + records = flowRecordBuilderService.createNextRecord(flowNode); + // 审批拒绝返回上一节点 + } else if (flowDirectionService.isDefaultBackRecord()) { + records = flowRecordBuilderService.createDefaultBackRecord(flowRecord.getPreId()); + } else { + // 审批拒绝,并且自定了返回节点 + records = flowRecordBuilderService.createCustomBackRecord(flowNode, flowRecord.getPreId()); + } + + // 保存流程记录 + flowRecordRepository.save(records); + + // 推送审批事件消息 + int eventState = flowSourceDirection == FlowSourceDirection.PASS ? FlowApprovalEvent.STATE_PASS : FlowApprovalEvent.STATE_REJECT; + EventPusher.push(new FlowApprovalEvent(eventState, flowRecord, currentOperator, flowWork, snapshot.toBindData())); + + // 推送待办事件消息 + for (FlowRecord record : records) { + IFlowOperator pushOperator = record.getCurrentOperator(); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, record, pushOperator, flowWork, snapshot.toBindData())); + } + + return new FlowResult(flowWork, records); + } + + + /** + * 撤回流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public void recall(long recordId, IFlowOperator currentOperator) { + FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + flowRecordService.loadFlowRecord(); + flowRecordService.verifyFlowRecordCurrentOperator(); + flowRecordService.loadFlowWork(); + flowRecordService.loadFlowNode(); + flowRecordService.verifyFlowRecordNotFinish(); + flowRecordService.verifyFlowRecordNotTodo(); + + FlowRecord flowRecord = flowRecordService.getFlowRecord(); + FlowWork flowWork = flowRecordService.getFlowWork(); + + // 下一流程的流程记录 + List childrenRecords = flowRecordRepository.findFlowRecordByPreId(recordId); + // 下一流程均为办理且未读 + + if (childrenRecords.isEmpty()) { + throw new IllegalArgumentException("flow record not submit"); + } + + boolean allUnDone = childrenRecords.stream().allMatch(item -> item.isUnRead() && item.isTodo()); + if (!allUnDone) { + throw new IllegalArgumentException("flow record not recall"); + } + flowRecord.recall(); + flowRecordRepository.update(flowRecord); + + flowRecordRepository.delete(childrenRecords); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_RECALL, flowRecord, currentOperator, flowWork, null)); + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/trigger/OutTrigger.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/trigger/OutTrigger.java new file mode 100644 index 00000000..b7281495 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/trigger/OutTrigger.java @@ -0,0 +1,44 @@ +package com.codingapi.springboot.flow.trigger; + +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.script.GroovyShellContext; +import lombok.Getter; +import org.springframework.util.StringUtils; + +/** + * 出口触发器 + */ +public class OutTrigger { + + @Getter + private final String script; + + private final GroovyShellContext.ShellScript runtime; + + public OutTrigger(String script) { + if (!StringUtils.hasLength(script)) { + throw new IllegalArgumentException("script is empty"); + } + this.script = script; + this.runtime = GroovyShellContext.getInstance().parse(script); + } + + /** + * 默认出口触发器 + */ + public static OutTrigger defaultOutTrigger() { + return new OutTrigger("def run(content) {return true;}"); + } + + + /** + * 触发 + * + * @param flowSession 流程内容 + * @return true 进入下一节点,false 则返回上一节点 + */ + public boolean trigger(FlowSession flowSession) { + return (Boolean) runtime.invokeMethod("run", flowSession); + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/user/IFlowOperator.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/user/IFlowOperator.java new file mode 100644 index 00000000..69dfa44d --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/user/IFlowOperator.java @@ -0,0 +1,36 @@ +package com.codingapi.springboot.flow.user; + +/** + * 流程参与用户 + */ +public interface IFlowOperator { + + /** + * 获取用户ID + * + * @return ID + */ + long getUserId(); + + + /** + * 获取用户名称 + * @return 名称 + */ + String getName(); + + + /** + * 是否流程管理员 + * 流程管理员可以强制干预流程 + */ + boolean isFlowManager(); + + + /** + * 委托操作者 + * 当委托操作者不为空时,当前操作者将由委托操作者执行 + */ + IFlowOperator entrustOperator(); + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/utils/Sha256Utils.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/utils/Sha256Utils.java new file mode 100644 index 00000000..c7a37b0b --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/utils/Sha256Utils.java @@ -0,0 +1,25 @@ +package com.codingapi.springboot.flow.utils; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class Sha256Utils { + + + public static String generateSHA256(String input) { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] hash = digest.digest(input.getBytes()); + StringBuilder hexString = new StringBuilder(); + for (byte b : hash) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) hexString.append('0'); + hexString.append(hex); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/springboot-starter-flow/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/springboot-starter-flow/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..3a985208 --- /dev/null +++ b/springboot-starter-flow/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.codingapi.springboot.flow.FlowConfiguration diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/FlowTestApplication.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/FlowTestApplication.java new file mode 100644 index 00000000..8a5c85d0 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/FlowTestApplication.java @@ -0,0 +1,12 @@ +package com.codingapi.springboot.flow; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class FlowTestApplication { + + public static void main(String[] args) { + SpringApplication.run(FlowTestApplication.class, args); + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave.java new file mode 100644 index 00000000..2d02fed0 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave.java @@ -0,0 +1,24 @@ +package com.codingapi.springboot.flow.flow; + +import com.codingapi.springboot.flow.bind.IBindData; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class Leave implements IBindData { + + private long id; + private String title; + private int days; + + public Leave(String title) { + this(title,0); + } + + public Leave(String title, int days) { + this.title = title; + this.days = days; + } + +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowBackupRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowBackupRepositoryImpl.java new file mode 100644 index 00000000..0efbb8cd --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowBackupRepositoryImpl.java @@ -0,0 +1,29 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.record.FlowBackup; + +import java.util.ArrayList; +import java.util.List; + +public class FlowBackupRepositoryImpl implements FlowBackupRepository{ + + private final List cache = new ArrayList<>(); + + @Override + public FlowBackup backup(FlowWork flowWork) { + FlowBackup flowBackup = new FlowBackup(flowWork); + cache.add(flowBackup); + return flowBackup; + } + + @Override + public FlowBackup getFlowBackupByWorkIdAndVersion(long workId, long workVersion) { + return cache.stream().filter(flowBackup -> flowBackup.getWorkId() == workId && flowBackup.getWorkVersion() == workVersion).findFirst().orElse(null); + } + + @Override + public FlowBackup getFlowBackupById(long backupId) { + return cache.stream().filter(flowBackup -> flowBackup.getId() == backupId).findFirst().orElse(null); + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowBindDataRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowBindDataRepositoryImpl.java new file mode 100644 index 00000000..2f3b8228 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowBindDataRepositoryImpl.java @@ -0,0 +1,38 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import lombok.AllArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@AllArgsConstructor +public class FlowBindDataRepositoryImpl implements FlowBindDataRepository { + + private final List cache = new ArrayList<>(); + + @Override + public void save(BindDataSnapshot snapshot) { + if (snapshot.getId() == 0) { + cache.add(snapshot); + snapshot.setId(cache.size()); + } + } + + @Override + public void update(BindDataSnapshot snapshot) { + BindDataSnapshot old = getBindDataSnapshotById(snapshot.getId()); + if (old != null) { + old.setSnapshot(snapshot.getSnapshot()); + } + } + + @Override + public BindDataSnapshot getBindDataSnapshotById(long id) { + return cache.stream().filter(snapshot -> snapshot.getId() == id).findFirst().orElse(null); + } + + public List findAll(){ + return cache; + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java new file mode 100644 index 00000000..782f0bae --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java @@ -0,0 +1,39 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.record.FlowBackup; +import com.codingapi.springboot.flow.record.FlowProcess; +import lombok.AllArgsConstructor; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@AllArgsConstructor +public class FlowProcessRepositoryImpl implements FlowProcessRepository { + + private final List cache = new ArrayList<>(); + private final FlowBackupRepository flowBackupRepository; + private final UserRepository userRepository; + + + @Override + public void save(FlowProcess flowProcess) { + List ids = cache.stream().map(FlowProcess::getProcessId).collect(Collectors.toList()); + if (!ids.contains(flowProcess.getProcessId())) { + cache.add(flowProcess); + } + } + + @Override + public FlowWork getFlowWorkByProcessId(String processId) { + FlowProcess process = cache.stream().filter(flowProcess -> flowProcess.getProcessId().equals(processId)).findFirst().orElse(null); + if (process == null) { + return null; + } + FlowBackup flowBackup = flowBackupRepository.getFlowBackupById(process.getBackupId()); + return flowBackup.resume(userRepository); + } + + +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java new file mode 100644 index 00000000..5875e22d --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java @@ -0,0 +1,104 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.query.FlowRecordQuery; +import com.codingapi.springboot.flow.record.FlowRecord; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class FlowRecordRepositoryImpl implements FlowRecordRepository, FlowRecordQuery { + + private final List cache = new ArrayList<>(); + + @Override + public void save(List records) { + for (FlowRecord record : records) { + if (record.getId() == 0) { + cache.add(record); + record.setId(cache.size()); + } + } + } + + @Override + public FlowRecord getFlowRecordById(long id) { + return cache.stream().filter(record -> record.getId() == id).findFirst().orElse(null); + } + + + @Override + public void update(FlowRecord flowRecord) { + if (flowRecord.getId() == 0) { + cache.add(flowRecord); + flowRecord.setId(cache.size()); + } + } + + @Override + public List findFlowRecordByPreId(long preId) { + return cache.stream().filter(record -> record.getPreId() == preId).collect(Collectors.toList()); + } + + @Override + public List findFlowRecordByProcessId(String processId) { + return cache.stream().filter(record -> record.getProcessId().equals(processId)) + .sorted((o1, o2) -> (int) (o1.getCreateTime() - o2.getCreateTime())) + .collect(Collectors.toList()); + } + + @Override + public List findTodoFlowRecordByProcessId(String processId) { + return cache.stream().filter(record -> record.isTodo() && record.getProcessId().equals(processId)).collect(Collectors.toList()); + } + + public Page findAll(PageRequest pageRequest) { + return new PageImpl<>(cache); + } + + @Override + public Page findDoneByOperatorId(long operatorId,PageRequest pageRequest) { + List flowRecords = cache.stream().filter(record -> record.isDone() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + + @Override + public Page findInitiatedByOperatorId(long operatorId,PageRequest pageRequest) { + List flowRecords = cache.stream().filter(record -> record.isInitiated() && record.getCreateOperator().getUserId() == operatorId).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + + @Override + public Page findTodoByOperatorId(long operatorId,PageRequest pageRequest) { + List flowRecords = cache.stream().filter(record -> record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + + @Override + public Page findTimeoutTodoByOperatorId(long operatorId,PageRequest pageRequest) { + List flowRecords = cache.stream().filter(record -> record.isTimeout() && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + + + @Override + public Page findPostponedTodoByOperatorId(long operatorId,PageRequest pageRequest) { + List flowRecords = cache.stream().filter(record -> record.isPostponed() && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + + @Override + public void finishFlowRecordByProcessId(String processId) { + cache.stream() + .filter(record -> record.getProcessId().equals(processId)) + .forEach(FlowRecord::finish); + } + + @Override + public void delete(List childrenRecords) { + cache.removeAll(childrenRecords); + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowWorkRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowWorkRepositoryImpl.java new file mode 100644 index 00000000..6e93dbea --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowWorkRepositoryImpl.java @@ -0,0 +1,34 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.domain.FlowWork; + +import java.util.ArrayList; +import java.util.List; + +public class FlowWorkRepositoryImpl implements FlowWorkRepository{ + + private final List cache = new ArrayList<>(); + + @Override + public FlowWork getFlowWorkById(long id) { + return cache.stream().filter(flowWork -> flowWork.getId() == id).findFirst().orElse(null); + } + + @Override + public FlowWork getFlowWorkByCode(String code) { + return cache.stream().filter(flowWork -> flowWork.getCode().equals(code)).findFirst().orElse(null); + } + + @Override + public void save(FlowWork flowWork) { + if(flowWork.getId()==0){ + cache.add(flowWork); + flowWork.setId(cache.size()); + } + } + + @Override + public void delete(long id) { + cache.removeIf(flowWork -> flowWork.getId() == id); + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/LeaveRepository.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/LeaveRepository.java new file mode 100644 index 00000000..dd4f50f1 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/LeaveRepository.java @@ -0,0 +1,18 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.flow.Leave; + +import java.util.ArrayList; +import java.util.List; + +public class LeaveRepository { + + private final List cache = new ArrayList<>(); + + public void save(Leave leave) { + if (leave.getId() == 0) { + cache.add(leave); + leave.setId(cache.size()); + } + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/UserRepository.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/UserRepository.java new file mode 100644 index 00000000..315bc040 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/UserRepository.java @@ -0,0 +1,39 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.flow.user.User; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class UserRepository implements FlowOperatorRepository { + + private final List cache = new ArrayList<>(); + + public void save(User user) { + if (user.getId() == 0) { + cache.add(user); + user.setId(cache.size()); + } + } + + public User getById(long id) { + for (User user : cache) { + if (user.getId() == id) { + return user; + } + } + return null; + } + + @Override + public IFlowOperator getFlowOperatorById(long createOperatorId) { + return getById(createOperatorId); + } + + @Override + public List findByIds(List ids) { + return cache.stream().filter(user -> ids.contains(user.getId())).collect(Collectors.toList()); + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/script/GroovyShellContextTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/script/GroovyShellContextTest.java new file mode 100644 index 00000000..80f655fd --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/script/GroovyShellContextTest.java @@ -0,0 +1,30 @@ +package com.codingapi.springboot.flow.script; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class GroovyShellContextTest { + + @Test + void getInstance() { + long t1 = System.currentTimeMillis(); + int count = 12000; + GroovyShellContext.ShellScript[] scripts = new GroovyShellContext.ShellScript[count]; + for (int i = 0; i < count; i++) { + scripts[i] = GroovyShellContext.getInstance().parse("def run(content){ return '" + i + "';}"); + } + + long t2 = System.currentTimeMillis(); + System.out.println("t2 time :" + (t2 - t1)); + System.out.println("size:" + GroovyShellContext.getInstance().size()); + + for (int i = 0; i < count; i++) { + assertEquals(scripts[i].invokeMethod("run", i), String.valueOf(i)); + } + + long t3 = System.currentTimeMillis(); + System.out.println("t3 time :" + (t3 - t2)); + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/BuildTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/BuildTest.java new file mode 100644 index 00000000..47c426a6 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/BuildTest.java @@ -0,0 +1,49 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.repository.UserRepository; +import com.codingapi.springboot.flow.serializable.FlowWorkSerializable; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class BuildTest { + + private final UserRepository userRepository = new UserRepository(); + + + @Test + void build() { + User user = new User("张三"); + userRepository.save(user); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + assertEquals("请假流程", flowWork.getTitle()); + assertEquals(4, flowWork.getNodes().size()); + assertEquals(3, flowWork.getRelations().size()); + + + byte[] bytes = flowWork.toSerializable().toSerializable(); + FlowWorkSerializable flowWorkSerializable = FlowWorkSerializable.fromSerializable(bytes); + assertEquals("请假流程", flowWorkSerializable.getTitle()); + + FlowWork serializableWork = flowWorkSerializable.toFlowWork(userRepository); + assertEquals("请假流程", serializableWork.getTitle()); + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java new file mode 100644 index 00000000..219b8472 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java @@ -0,0 +1,218 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.error.ErrTrigger; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ErrorTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository,userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository,flowProcessRepository,flowBackupRepository); + + + /** + * 异常节点触发器 + * 异常时配置其他人来审批 + */ + @Test + void errorMatcherOperatorTest(){ + PageRequest pageRequest = PageRequest.of(0, 1000); + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createOperatorErrTrigger("+dept.getId()+")}"), true) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + // 保存流程 + leave.setTitle("我要出去看看~~"); + flowService.save(userTodo.getId(), user, leave,"暂存"); + + // 查看流程详情 + FlowDetail flowDetail = flowService.detail(userTodo.getId(), user); + assertEquals("我要出去看看~~", ((Leave)flowDetail.getBindData()).getTitle()); + assertTrue(flowDetail.getFlowRecord().isRead()); + + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + } + + + + /** + * 异常节点触发器 + * 异常时配置其节点来审批 + */ + @Test + void errorMatcherNodeTest(){ + + PageRequest pageRequest = PageRequest.of(0,1000); + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createNodeErrTrigger('manager')}"), true) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + // 保存流程 + leave.setTitle("我要出去看看~~"); + flowService.save(userTodo.getId(), user, leave,"暂存"); + + // 查看流程详情 + FlowDetail flowDetail = flowService.detail(userTodo.getId(), user); + assertEquals("我要出去看看~~", ((Leave)flowDetail.getBindData()).getTitle()); + assertTrue(flowDetail.getFlowRecord().isRead()); + + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java new file mode 100644 index 00000000..40bcb8b4 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java @@ -0,0 +1,821 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class FlowTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository,userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository,flowProcessRepository,flowBackupRepository); + + /** + * 委托测试测试 + */ + @Test + void entrustTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备", lorne); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + // 保存流程 + leave.setTitle("我要出去看看~~"); + flowService.save(userTodo.getId(), user, leave,"暂存"); + + // 查看流程详情 + FlowDetail flowDetail = flowService.detail(userTodo.getId(), user); + assertEquals("我要出去看看~~", ((Leave) flowDetail.getBindData()).getTitle()); + assertTrue(flowDetail.getFlowRecord().isRead()); + + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + List lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + // 提交委托lorne部门经理的审批 + FlowRecord lorneTodo = lorneTodos.get(0); + flowService.submitFlow(lorneTodo.getId(), lorne, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + + } + + + + /** + * 同意再拒绝 + */ + @Test + void passAndRejectTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("总经理审批", "manager", "default", ApprovalType.SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("开始节点", "start", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(1, records.size()); + + + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + + } + + /** + * 全部通过测试 + */ + @Test + void passTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + // 保存流程 + leave.setTitle("我要出去看看~~"); + flowService.save(userTodo.getId(), user, leave,"暂存"); + + // 查看流程详情 + FlowDetail flowDetail = flowService.detail(userTodo.getId(), user); + assertEquals("我要出去看看~~", ((Leave) flowDetail.getBindData()).getTitle()); + assertTrue(flowDetail.getFlowRecord().isRead()); + + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + + } + + + /** + * 节点禁止保存通过测试 + */ + @Test + void saveDisableTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId()), false) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + leave.setTitle("我要出去看看~~"); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + assertEquals("我要出去看看", ((Leave) flowService.detail(deptTodo.getId()).getBindData()).getTitle()); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + + } + + /** + * 干预流程 + */ + @Test + void interfereTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User admin = new User("lorne", true); + userRepository.save(admin); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.interfere(userTodo.getId(), admin, leave, Opinion.pass("同意")); + assertTrue(userTodo.isInterfere()); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.interfere(deptTodo.getId(), admin, leave, Opinion.pass("同意")); + assertTrue(deptTodo.isInterfere()); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.interfere(bossTodo.getId(), admin, leave, Opinion.pass("同意")); + assertTrue(bossTodo.isInterfere()); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + } + + + /** + * 转办流程 + */ + @Test + void transferTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + + // 转交给lorne处理 + FlowRecord deptTodo = deptTodos.get(0); + flowService.transfer(deptTodo.getId(), dept, lorne, leave, "转办给lorne"); + + assertTrue(deptTodo.isTransfer()); + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + List lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + FlowRecord lorneTodo = lorneTodos.get(0); + + flowService.submitFlow(lorneTodo.getId(), lorne, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(6, snapshots.size()); + } + + + /** + * 催办与延期测试 + */ + @Test + void postponedAndUrgeTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + + // 查看流程详情 + FlowDetail flowDetail = flowService.detail(userTodo.getId()); + assertEquals("我要出去看看", ((Leave) flowDetail.getBindData()).getTitle()); + assertTrue(flowDetail.getFlowRecord().isUnRead()); + + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + + FlowRecord deptTodo = deptTodos.get(0); + + + // 延期10000毫米 + flowService.postponed(deptTodo.getId(), dept, 10000); + + long latestTimeOutTime = deptTodo.getTimeoutTime(); + long currentTime = System.currentTimeMillis(); + + assertTrue(latestTimeOutTime - currentTime >= 10000); + + // 再延期将会出现异常 + assertThrows(Exception.class, () -> flowService.postponed(deptTodo.getId(), dept, 10000)); + + // 催办 + flowService.urge(userTodo.getId(), user); + + // 待办下催办出现异常 + assertThrows(Exception.class, () -> flowService.postponed(deptTodo.getId(), dept, 10000)); + + } + + /** + * 部门拒绝再提交测试 + */ + @Test + void rejectTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + + // 查看流程详情 + FlowDetail flowDetail = flowService.detail(userTodo.getId()); + assertEquals("我要出去看看", ((Leave) flowDetail.getBindData()).getTitle()); + assertTrue(flowDetail.getFlowRecord().isUnRead()); + + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.reject("不同意")); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(6, records.size()); + + + } + + + /** + * 撤销流程测试 + */ + @Test + void recallTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 撤销流程 + flowService.recall(userTodo.getId(), user); + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.reject("不同意")); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(6, records.size()); + + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java new file mode 100644 index 00000000..ecc58e5c --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java @@ -0,0 +1,113 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class FlowTest2 { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository,userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository,flowProcessRepository,flowBackupRepository); + + /** + * flow test + */ + @Test + void flowTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + User lorne = new User("lorne"); + userRepository.save(lorne); + + User boss = new User("boss"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(lorne) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("老板审批", "boss", "default", ApprovalType.SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("老板审批", "start", "boss") + .relation("结束节点", "boss", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我想要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, lorne, leave, "发起流程"); + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), lorne, leave, Opinion.pass("自己提交")); + + // 部门领导审批 + List deptTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + FlowRecord deptTodo = deptTodos.get(0); + assertNull(deptTodo.getOpinion()); + flowService.transfer(deptTodo.getId(), lorne,boss, leave, "转交给领导审批通过"); + + // 查看boss的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.reject("领导审批不通过")); + + userTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + assertEquals(FlowNode.CODE_START, userTodo.getNodeCode()); + + flowService.submitFlow(userTodo.getId(), lorne, leave, Opinion.pass("自己再次提交")); + + deptTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), lorne, leave, Opinion.pass("转交给领导审批通过")); + + bossTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), lorne, leave, Opinion.pass("领导审批通过")); + + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(6, records.size()); + + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java new file mode 100644 index 00000000..f9d09469 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java @@ -0,0 +1,314 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.trigger.OutTrigger; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MultiRelationFlowTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository,userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository,flowProcessRepository,flowBackupRepository); + + /** + * 多条件流程测试 + * (直接走结束,没有流转老板测试) + */ + @Test + void relationTest1(){ + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "over",new OutTrigger("def run(content){content.getBindData().getDays()<=5}"),1,false) + .relation("总经理审批", "dept", "manager",new OutTrigger("def run(content){content.getBindData().getDays()>5}"),2,false) + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看",5); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + + // 最终用户确认 + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + } + + + + + /** + * 多条件流程测试 + * (流转老板测试) + */ + @Test + void relationTest2(){ + + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "over",new OutTrigger("def run(content){content.getBindData().getDays()<=5}"),1,false) + .relation("总经理审批", "dept", "manager",new OutTrigger("def run(content){content.getBindData().getDays()>5}"),2,false) + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看",6); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + + // 查看老板的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交老板的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + // 最终用户确认 + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + } + + + + /** + * 多条件流程测试撤回 + */ + @Test + void relationTest3(){ + + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "over",new OutTrigger("def run(content){content.getBindData().getDays()<=5}"),1,false) + .relation("总经理审批", "dept", "manager",new OutTrigger("def run(content){content.getBindData().getDays()>5}"),2,false) + .relation("结束节点", "manager", "start",new OutTrigger("def run(content){return true}"),1,true) + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看",6); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + + // 查看老板的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交老板的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.reject("不同意,最多让你请假3天")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + // 用户修改确认 + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 用户调整为3天 + leave.setDays(3); + // 提交流程 + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 用户修改确认 + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(7, snapshots.size()); + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/QueryTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/QueryTest.java new file mode 100644 index 00000000..d975ec01 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/QueryTest.java @@ -0,0 +1,540 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class QueryTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository,userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository,flowProcessRepository,flowBackupRepository); + + /** + * 查询用户的待办 + */ + @Test + void queryUserToDo(){ + + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(0, bossTodos.size()); + + } + + + /** + * 查询用户的超时待办 + */ + @Test + void queryUserTimeoutTodo(){ + + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher(),100,true) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 查看我的超时待办 + List userTimeOutTodos = flowRecordRepository.findTimeoutTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTimeOutTodos.size()); + + try { + Thread.sleep(200); + } catch (InterruptedException ignore) {} + + userTimeOutTodos = flowRecordRepository.findTimeoutTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTimeOutTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent();; + assertEquals(4, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + + userTodos = flowRecordRepository.findTimeoutTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + deptTodos = flowRecordRepository.findTimeoutTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + bossTodos = flowRecordRepository.findTimeoutTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(0, bossTodos.size()); + + } + + + + /** + * 查询用户的延期待办 + */ + @Test + void queryUserPostponedTodo(){ + + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher(),100,true) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 延期待办 + FlowRecord userTodo = userTodos.get(0); + flowService.postponed(userTodo.getId(), user,100); + + // 查看我的延期待办 + List userPostponedTodos = flowRecordRepository.findPostponedTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userPostponedTodos.size()); + + // 查看我的超时待办 + List userTimeOutTodos = flowRecordRepository.findTimeoutTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTimeOutTodos.size()); + + try { + Thread.sleep(200); + } catch (InterruptedException ignore) {} + + userTimeOutTodos = flowRecordRepository.findTimeoutTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTimeOutTodos.size()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + + userTodos = flowRecordRepository.findPostponedTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + deptTodos = flowRecordRepository.findPostponedTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + bossTodos = flowRecordRepository.findPostponedTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(0, bossTodos.size()); + + } + + + /** + * 查询用户的已办 + */ + @Test + void queryUserDone(){ + + PageRequest pageRequest = PageRequest.of(0, 1000); + + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + FlowDetail flowDetail = flowService.detail(records.get(0).getId(), user); + assertEquals(4, flowDetail.getHistoryRecords().size()); + assertEquals(4, flowDetail.getOpinions().size()); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + + + List userDones = flowRecordRepository.findDoneByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(2, userDones.size()); + + List deptDones = flowRecordRepository.findDoneByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptDones.size()); + + List bossDones = flowRecordRepository.findDoneByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossDones.size()); + + } + + + /** + * 查询用户发起的流程 + */ + @Test + void queryUserInitiated(){ + + PageRequest pageRequest = PageRequest.of(0, 1000); + + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + + + + List userInitiates = flowRecordRepository.findInitiatedByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userInitiates.size()); + + List deptInitiates = flowRecordRepository.findInitiatedByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptInitiates.size()); + + List bossInitiates = flowRecordRepository.findInitiatedByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(0, bossInitiates.size()); + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java new file mode 100644 index 00000000..ce99c991 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java @@ -0,0 +1,43 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class ScriptBuildTest { + + + @Test + void copy() { + User user = new User("张三"); + String script = "{\"nodes\":[{\"id\":\"e7699cab-e20b-4606-af66-fb8d782fd0f8\",\"type\":\"start-node\",\"x\":1005,\"y\":153,\"properties\":{\"name\":\"开始节点\",\"code\":\"start\",\"type\":\"START\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCreateOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCreateOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"e7699cab-e20b-4606-af66-fb8d782fd0f8\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"creator\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"0d6638e9-0f98-45de-a5ad-8d55702158f7\",\"type\":\"node-node\",\"x\":722,\"y\":392,\"properties\":{\"name\":\"部门审批\",\"code\":\"dept\",\"type\":\"APPROVAL\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCreateOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"SIGN\",\"timeout\":0,\"id\":\"0d6638e9-0f98-45de-a5ad-8d55702158f7\",\"width\":200,\"height\":45}},{\"id\":\"c4f8dd1b-53f2-4a87-8f57-9828b79fc4d0\",\"type\":\"over-node\",\"x\":918,\"y\":773,\"properties\":{\"name\":\"结束节点\",\"code\":\"over\",\"type\":\"OVER\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCreateOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"c4f8dd1b-53f2-4a87-8f57-9828b79fc4d0\",\"width\":200,\"height\":45}},{\"id\":\"ed654f48-c94c-4fdd-9b14-91f6295ae17a\",\"type\":\"node-node\",\"x\":1227,\"y\":530,\"properties\":{\"name\":\"老板审批\",\"code\":\"boss\",\"type\":\"APPROVAL\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCreateOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"SIGN\",\"timeout\":0,\"id\":\"ed654f48-c94c-4fdd-9b14-91f6295ae17a\",\"width\":200,\"height\":45}}],\"edges\":[{\"id\":\"6854a4ef-89cf-48d3-9aa7-af1e5b87e93c\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":2,\"back\":false},\"sourceNodeId\":\"e7699cab-e20b-4606-af66-fb8d782fd0f8\",\"targetNodeId\":\"0d6638e9-0f98-45de-a5ad-8d55702158f7\",\"startPoint\":{\"x\":1005,\"y\":175.5},\"endPoint\":{\"x\":722,\"y\":369.5},\"pointsList\":[{\"x\":1005,\"y\":175.5},{\"x\":1005,\"y\":275.5},{\"x\":722,\"y\":269.5},{\"x\":722,\"y\":369.5}]},{\"id\":\"7c2c01fc-ded1-46e7-baf7-9fa664898d74\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"0d6638e9-0f98-45de-a5ad-8d55702158f7\",\"targetNodeId\":\"c4f8dd1b-53f2-4a87-8f57-9828b79fc4d0\",\"startPoint\":{\"x\":722,\"y\":414.5},\"endPoint\":{\"x\":918,\"y\":750.5},\"pointsList\":[{\"x\":722,\"y\":414.5},{\"x\":722,\"y\":514.5},{\"x\":918,\"y\":650.5},{\"x\":918,\"y\":750.5}]},{\"id\":\"67ee0fe7-b88c-4fde-be82-e23276f567e6\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"e7699cab-e20b-4606-af66-fb8d782fd0f8\",\"targetNodeId\":\"ed654f48-c94c-4fdd-9b14-91f6295ae17a\",\"startPoint\":{\"x\":1005,\"y\":175.5},\"endPoint\":{\"x\":1227,\"y\":507.5},\"pointsList\":[{\"x\":1005,\"y\":175.5},{\"x\":1005,\"y\":275.5},{\"x\":1227,\"y\":407.5},{\"x\":1227,\"y\":507.5}]},{\"id\":\"9c6f3b0c-03f5-46eb-be39-c79528a824dc\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"ed654f48-c94c-4fdd-9b14-91f6295ae17a\",\"targetNodeId\":\"c4f8dd1b-53f2-4a87-8f57-9828b79fc4d0\",\"startPoint\":{\"x\":1227,\"y\":552.5},\"endPoint\":{\"x\":918,\"y\":750.5},\"pointsList\":[{\"x\":1227,\"y\":552.5},{\"x\":1227,\"y\":652.5},{\"x\":918,\"y\":650.5},{\"x\":918,\"y\":750.5}]}]}"; + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .schema(script) + .build(); + assertEquals("请假流程", flowWork.getTitle()); + assertEquals(4, flowWork.getNodes().size()); + assertEquals(4, flowWork.getRelations().size()); + + + FlowNode startNode = flowWork.getStartNode(); + + FlowWork copyWork = flowWork.copy(); + assertNotEquals(copyWork.getCode(), flowWork.getCode()); + + assertEquals("请假流程", copyWork.getTitle()); + assertEquals(4, copyWork.getNodes().size()); + assertEquals(4, copyWork.getRelations().size()); + + copyWork.verify(); + + FlowNode startNode2 = copyWork.getNodeByCode("start"); + assertNotEquals(startNode.getId(), startNode2.getId()); + + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptTest.java new file mode 100644 index 00000000..d2f9d9e7 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptTest.java @@ -0,0 +1,72 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.generator.TitleGenerator; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.repository.UserRepository; +import com.codingapi.springboot.flow.trigger.OutTrigger; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ScriptTest { + + private final UserRepository userRepository = new UserRepository(); + + @Test + void test() { + User user = new User("张三"); + userRepository.save(user); + + OperatorMatcher matcher = OperatorMatcher.anyOperatorMatcher(); + + OperatorMatcher operatorMatcher = OperatorMatcher.anyOperatorMatcher(); + + TitleGenerator titleGenerator = TitleGenerator.defaultTitleGenerator(); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, operatorMatcher) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, operatorMatcher) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, operatorMatcher) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, operatorMatcher) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + OutTrigger outTrigger =OutTrigger.defaultOutTrigger(); + OperatorMatcher specifyOperatorMatcher = OperatorMatcher.specifyOperatorMatcher(1); + + long now = System.currentTimeMillis(); + Leave leave = new Leave("我要请假"); + + FlowSession flowSession = new FlowSession(flowWork, flowWork.getNodeByCode("start"), user, user, leave, Opinion.pass("同意"),new ArrayList<>()); + + List ids = matcher.matcher(flowSession); + assertTrue(ids.contains(user.getUserId())); + + String title = titleGenerator.generate(flowSession); + assertEquals("张三-请假流程-开始节点", title); + + boolean next = outTrigger.trigger(flowSession); + assertTrue(next); + + List userIds = specifyOperatorMatcher.matcher(flowSession); + assertTrue(userIds.contains(1L)); + + long time = System.currentTimeMillis() - now; + System.out.println("time:" + time); + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java new file mode 100644 index 00000000..d5128b83 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java @@ -0,0 +1,415 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class SignTest { + + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository,userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository,flowProcessRepository,flowBackupRepository); + + /** + * 多人非会签测试 + */ + @Test + void unSignTest(){ + PageRequest pageRequest = PageRequest.of(0, 1000); + + User caocao = new User("曹操"); + userRepository.save(caocao); + User lvBu = new User("吕布"); + userRepository.save(lvBu); + User zhaoYun = new User("赵云"); + userRepository.save(zhaoYun); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, + OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),caocao.getUserId(),lvBu.getUserId(),zhaoYun.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(zhaoYun.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), zhaoYun, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent();; + assertEquals(7, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(7, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + + } + + + + /** + * 多人会签测试 + */ + @Test + void signTest(){ + PageRequest pageRequest = PageRequest.of(0, 1000); + + User caocao = new User("曹操"); + userRepository.save(caocao); + User lvBu = new User("吕布"); + userRepository.save(lvBu); + User zhaoYun = new User("赵云"); + userRepository.save(zhaoYun); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.SIGN, + OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),caocao.getUserId(),lvBu.getUserId(),zhaoYun.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("用户同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("刘备同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(0, bossTodos.size()); + + // 查看部门经理 吕布 的待办 + List lvbuTodos = flowRecordRepository.findTodoByOperatorId(lvBu.getUserId(), pageRequest).getContent(); + assertEquals(1, lvbuTodos.size()); + + // 提交部门经理 吕布 的审批 + FlowRecord lvbuTodo = lvbuTodos.get(0); + flowService.submitFlow(lvbuTodo.getId(), lvBu, leave, Opinion.pass("吕布同意")); + + + // 查看部门经理 赵云 的待办 + List zhaoYunTodos = flowRecordRepository.findTodoByOperatorId(zhaoYun.getUserId(), pageRequest).getContent(); + assertEquals(1, zhaoYunTodos.size()); + + // 提交部门经理 赵云 的审批 + FlowRecord zhaoYunTodo = zhaoYunTodos.get(0); + flowService.submitFlow(zhaoYunTodo.getId(), zhaoYun, leave, Opinion.pass("赵云同意")); + + + // 查看部门经理 曹操 的待办 + List caocaoTodos = flowRecordRepository.findTodoByOperatorId(caocao.getUserId(), pageRequest).getContent(); + assertEquals(1, caocaoTodos.size()); + + // 提交部门经理 曹操 的审批 + FlowRecord caocaoTodo = caocaoTodos.get(0); + flowService.submitFlow(caocaoTodo.getId(), caocao, leave, Opinion.pass("曹操同意")); + + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(7, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(7, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(8, snapshots.size()); + + } + + + + + /** + * 多人会签 有人拒绝测试 + */ + @Test + void signRejectTest(){ + + PageRequest pageRequest = PageRequest.of(0, 1000); + + User caocao = new User("曹操"); + userRepository.save(caocao); + User lvBu = new User("吕布"); + userRepository.save(lvBu); + User zhaoYun = new User("赵云"); + userRepository.save(zhaoYun); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.SIGN, + OperatorMatcher.specifyOperatorMatcher( + dept.getUserId(), + caocao.getUserId(), + lvBu.getUserId(), + zhaoYun.getUserId() + )) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("用户同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.reject("刘备不同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(0, bossTodos.size()); + + // 查看部门经理 吕布 的待办 + List lvbuTodos = flowRecordRepository.findTodoByOperatorId(lvBu.getUserId(), pageRequest).getContent(); + assertEquals(1, lvbuTodos.size()); + + // 提交部门经理 吕布 的审批 + FlowRecord lvbuTodo = lvbuTodos.get(0); + flowService.submitFlow(lvbuTodo.getId(), lvBu, leave, Opinion.pass("吕布同意")); + + + // 查看部门经理 赵云 的待办 + List zhaoYunTodos = flowRecordRepository.findTodoByOperatorId(zhaoYun.getUserId(), pageRequest).getContent(); + assertEquals(1, zhaoYunTodos.size()); + + // 提交部门经理 赵云 的审批 + FlowRecord zhaoYunTodo = zhaoYunTodos.get(0); + flowService.submitFlow(zhaoYunTodo.getId(), zhaoYun, leave, Opinion.pass("赵云同意")); + + + // 查看部门经理 曹操 的待办 + List caocaoTodos = flowRecordRepository.findTodoByOperatorId(caocao.getUserId(), pageRequest).getContent(); + assertEquals(1, caocaoTodos.size()); + + // 提交部门经理 曹操 的审批 + FlowRecord caocaoTodo = caocaoTodos.get(0); + flowService.submitFlow(caocaoTodo.getId(), caocao, leave, Opinion.pass("曹操同意")); + + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(0, bossTodos.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("用户同意")); + + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("刘备同意")); + + + lvbuTodos = flowRecordRepository.findTodoByOperatorId(lvBu.getUserId(), pageRequest).getContent(); + assertEquals(1, lvbuTodos.size()); + + // 提交部门经理 吕布 的审批 + lvbuTodo = lvbuTodos.get(0); + flowService.submitFlow(lvbuTodo.getId(), lvBu, leave, Opinion.pass("吕布同意")); + + + zhaoYunTodos = flowRecordRepository.findTodoByOperatorId(zhaoYun.getUserId(), pageRequest).getContent(); + assertEquals(1, zhaoYunTodos.size()); + + // 提交部门经理 赵云 的审批 + zhaoYunTodo = zhaoYunTodos.get(0); + flowService.submitFlow(zhaoYunTodo.getId(), zhaoYun, leave, Opinion.pass("赵云同意")); + + caocaoTodos = flowRecordRepository.findTodoByOperatorId(caocao.getUserId(), pageRequest).getContent(); + assertEquals(1, caocaoTodos.size()); + + // 提交部门经理 曹操 的审批 + caocaoTodo = caocaoTodos.get(0); + flowService.submitFlow(caocaoTodo.getId(), caocao, leave, Opinion.pass("曹操同意")); + + + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent();; + assertEquals(12, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(12, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(13, snapshots.size()); + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/user/User.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/user/User.java new file mode 100644 index 00000000..5a260782 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/user/User.java @@ -0,0 +1,46 @@ +package com.codingapi.springboot.flow.user; + +import lombok.Getter; +import lombok.Setter; + +@Getter +public class User implements IFlowOperator{ + + @Setter + private long id; + + private String name; + + private boolean isFlowManager; + + private User entrustOperator; + + public User(String name,boolean isFlowManager) { + this.name = name; + this.isFlowManager = isFlowManager; + } + + public User(String name,User entrustOperator) { + this.name = name; + this.entrustOperator = entrustOperator; + } + + public User(String name) { + this(name,false); + } + + @Override + public IFlowOperator entrustOperator() { + return entrustOperator; + } + + @Override + public long getUserId() { + return id; + } + + @Override + public boolean isFlowManager() { + return isFlowManager; + } +} diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 11b91dab..70d558a1 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.8.11 + 2.9.0 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index ca03cc75..167d7c35 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.8.11 + 2.9.0 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/ApplicationHandlerUtils.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/ApplicationHandlerUtils.java index 0e97bc4a..61c7a932 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/ApplicationHandlerUtils.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/ApplicationHandlerUtils.java @@ -2,9 +2,12 @@ import com.codingapi.springboot.framework.exception.EventException; import com.codingapi.springboot.framework.exception.EventLoopException; +import org.springframework.core.ResolvableType; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; class ApplicationHandlerUtils implements IHandler { @@ -40,18 +43,37 @@ public void addHandler(IHandler handler) { } } + /** + * 获取订阅的事件类型 + */ + private Class getHandlerEventClass(IHandler handler) { + ResolvableType resolvableType = ResolvableType.forClass(handler.getClass()).as(IHandler.class); + return resolvableType.getGeneric(0).resolve(); + } + @Override public void handler(IEvent event) { Class eventClass = event.getClass(); + + List> matchHandlers = handlers + .stream() + .filter(handler -> { + Class targetClass = getHandlerEventClass(handler); + return targetClass.isAssignableFrom(eventClass); + }) + .sorted(Comparator.comparingInt(IHandler::order)) + .collect(Collectors.toList()); + + if (matchHandlers.isEmpty()) { + return; + } + List errorStack = new ArrayList<>(); - boolean throwException = false; - for (IHandler handler : handlers) { + boolean hasThrowException = false; + for (IHandler handler : matchHandlers) { try { - Class targetClass = handler.getHandlerEventClass(); - if (eventClass.equals(targetClass)) { - handler.handler(event); - } + handler.handler(event); } catch (Exception e) { if (e instanceof EventLoopException) { throw e; @@ -60,12 +82,12 @@ public void handler(IEvent event) { handler.error(e); errorStack.add(e); } catch (Exception err) { - throwException = true; + hasThrowException = true; errorStack.add(err); } } } - if(throwException){ + if (hasThrowException) { throw new EventException(errorStack); } } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IEvent.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IEvent.java index 327ca279..4cc12388 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IEvent.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IEvent.java @@ -12,5 +12,4 @@ */ public interface IEvent extends Serializable { - } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IHandler.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IHandler.java index 226ee17d..46248d8c 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IHandler.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/IHandler.java @@ -1,7 +1,5 @@ package com.codingapi.springboot.framework.event; -import org.springframework.core.ResolvableType; - /** * handler 订阅 * @@ -9,6 +7,14 @@ */ public interface IHandler { + /** + * 事件订阅排序 + * 在同样的事件中,可以通过order来控制订阅的顺序 + */ + default int order() { + return 0; + } + /** * 订阅触发 * @@ -27,13 +33,6 @@ default void error(Exception exception) throws Exception { } - /** - * 获取订阅的事件类型 - */ - default Class getHandlerEventClass() { - ResolvableType resolvableType = ResolvableType.forClass(getClass()).as(IHandler.class); - return resolvableType.getGeneric(0).resolve(); - } } From 98c8e1d67ddf4a8e10e2128f8276788e924f23ca Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 9 Nov 2024 10:57:41 +0800 Subject: [PATCH 054/129] update readme --- README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6b653203..68fea27b 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,14 @@ ## Project Version | 项目版本说明 -v.2.x 为springboot 2.x版本,使用jdk8版本 -v.3.x 为springboot 3.x版本,使用jdk17版本 +v.2.x 为springboot 2.x版本,使用jdk8版本 +v.3.x 为springboot 3.x版本,使用jdk17版本 ## Project Modules Description | 项目模块介绍 * springboot-starter | Springboot领域驱动框架 * springboot-starter-data-fast | 快速数据呈现框架 +* springboot-starter-flow | 流程引擎框架 * springboot-starter-security | security权限框架支持基于JWT的无状态权限认证与Redis的有状态权限认证 ## SpringBoot DDD Architecture | SpringBoot DDD 框架图 @@ -41,6 +42,13 @@ v.3.x 为springboot 3.x版本,使用jdk17版本 ${last.version} + + + com.codingapi.springboot + springboot-starter-flow + ${last.version} + + com.codingapi.springboot @@ -63,7 +71,7 @@ https://github.com/codingapi/springboot-framework/wiki ## Example -见 [springboot-example](https://github.com/codingapi/springboot-example) +见 [springboot-example](https://github.com/codingapi/springboot-example) ## Reference Documentation From f39dfce1888ab41cc4ab350216fa7d3e1ce3810b Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 9 Nov 2024 15:25:51 +0800 Subject: [PATCH 055/129] support loop event pusher --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/event/DomainEventContext.java | 14 ++++++---- .../framework/event/EventPusher.java | 18 ++++++++++++- .../framework/event/EventTraceContext.java | 26 +++++++++++++++++++ 8 files changed, 57 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index ceb40070..18f5d46e 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.0 + 2.9.1 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 012a2759..f6b82eca 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.0 + 2.9.1 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index c2d61cc1..c5bcd2f6 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.0 + 2.9.1 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 70d558a1..5fcce435 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.0 + 2.9.1 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 167d7c35..7291503a 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.0 + 2.9.1 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEventContext.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEventContext.java index a22799e2..7d10e38c 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEventContext.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/DomainEventContext.java @@ -23,9 +23,13 @@ public static DomainEventContext getInstance() { return instance; } - private void push(IEvent event, boolean sync) { + private void push(IEvent event, boolean sync,boolean hasLoopEvent) { if (context != null) { String traceId = EventTraceContext.getInstance().getOrCreateTrace(); + if(hasLoopEvent){ + EventTraceContext.getInstance().clearTrace(); + traceId = EventTraceContext.getInstance().getOrCreateTrace(); + } EventTraceContext.getInstance().addEvent(traceId,event); context.publishEvent(new DomainEvent(event, sync,traceId)); } @@ -36,13 +40,13 @@ private void push(IEvent event, boolean sync) { * @see EventPusher * 默认 同步事件 */ - public void push(IEvent event) { + public void push(IEvent event,boolean hasLoopEvent) { if (event instanceof IAsyncEvent) { - this.push(event, false); + this.push(event, false,hasLoopEvent); } else if (event instanceof ISyncEvent) { - this.push(event, true); + this.push(event, true,hasLoopEvent); } else { - this.push(event, true); + this.push(event, true,hasLoopEvent); } } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventPusher.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventPusher.java index ee90ddd8..333569ea 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventPusher.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventPusher.java @@ -5,7 +5,23 @@ */ public class EventPusher { + /** + * 推送事件 + * 默认将自动检测事件是否有循环事件,当出现循环事件时,系统将会抛出循环调用异常。 + * @param event 事件 + */ public static void push(IEvent event) { - DomainEventContext.getInstance().push(event); + push(event, false); + } + + /** + * 推送事件 + * 默认将自动检测事件是否有循环事件,当出现循环事件时,系统将会抛出循环调用异常。 + * 设置hasLoopEvent为true,将不会检测循环事件。 + * @param event 事件 + * @param hasLoopEvent 是否有循环事件 + */ + public static void push(IEvent event, boolean hasLoopEvent) { + DomainEventContext.getInstance().push(event, hasLoopEvent); } } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventTraceContext.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventTraceContext.java index 844d2cf9..562e2768 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventTraceContext.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventTraceContext.java @@ -45,12 +45,19 @@ public String getEventKey() { return threadLocal.get(); } + /** + * create event key + * @param traceId traceId + */ void createEventKey(String traceId) { String eventKey = traceId + "#" + RandomGenerator.randomString(8); eventKeyState.put(eventKey, false); threadLocal.set(eventKey); } + /** + * check event state + */ void checkEventState() { String eventKey = threadLocal.get(); if (eventKey != null) { @@ -66,6 +73,11 @@ void checkEventState() { threadLocal.remove(); } + /** + * add event + * @param traceId traceId + * @param event event + */ void addEvent(String traceId, IEvent event) { boolean hasEventLoop = EventStackContext.getInstance().checkEventLoop(traceId, event); if (hasEventLoop) { @@ -78,4 +90,18 @@ void addEvent(String traceId, IEvent event) { } EventStackContext.getInstance().addEvent(traceId, event); } + + /** + * clear trace + */ + public void clearTrace() { + String eventKey = threadLocal.get(); + if (eventKey != null) { + String traceId = eventKey.split("#")[0]; + traceKeys.remove(traceId); + EventStackContext.getInstance().remove(traceId); + eventKeyState.remove(eventKey); + threadLocal.remove(); + } + } } From 510e84a86391f88f4f38648bde7364aae409b90c Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 9 Nov 2024 16:11:49 +0800 Subject: [PATCH 056/129] add FlowService push loop event --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/service/FlowService.java | 18 +++++++++--------- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index 18f5d46e..593898fb 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.1 + 2.9.2 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index f6b82eca..773213a8 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.1 + 2.9.2 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index c5bcd2f6..92e666e4 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.1 + 2.9.2 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index 25309652..a38930a6 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -99,7 +99,7 @@ public void urge(long recordId, IFlowOperator currentOperator) { // 推送催办消息 for (FlowRecord record : todoRecords) { IFlowOperator pushOperator = record.getCurrentOperator(); - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_URGE, record, pushOperator, flowWork, null)); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_URGE, record, pushOperator, flowWork, null),true); } } @@ -222,10 +222,10 @@ public void transfer(long recordId, IFlowOperator currentOperator, IFlowOperator flowRecordRepository.save(Collections.singletonList(transferRecord)); // 推送转办消息 - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TRANSFER, flowRecord, currentOperator, flowWork, snapshot.toBindData())); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TRANSFER, flowRecord, currentOperator, flowWork, snapshot.toBindData()),true); // 推送待办消息 - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, transferRecord, targetOperator, flowWork, snapshot.toBindData())); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, transferRecord, targetOperator, flowWork, snapshot.toBindData()),true); } @@ -329,8 +329,8 @@ public FlowResult startFlow(String workCode, IFlowOperator operator, IBindData b // 推送事件消息 for (FlowRecord record : records) { - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_CREATE, record, operator, flowWork, snapshot.toBindData())); - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, record, operator, flowWork, snapshot.toBindData())); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_CREATE, record, operator, flowWork, snapshot.toBindData()),true); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, record, operator, flowWork, snapshot.toBindData()),true); } // 当前的审批记录 return new FlowResult(flowWork, records); @@ -428,7 +428,7 @@ public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBind flowRecordRepository.update(flowRecord); flowRecordRepository.finishFlowRecordByProcessId(flowRecord.getProcessId()); - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_FINISH, flowRecord, currentOperator, flowWork, snapshot.toBindData())); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_FINISH, flowRecord, currentOperator, flowWork, snapshot.toBindData()),true); return new FlowResult(flowWork, flowRecord); } @@ -467,12 +467,12 @@ public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBind // 推送审批事件消息 int eventState = flowSourceDirection == FlowSourceDirection.PASS ? FlowApprovalEvent.STATE_PASS : FlowApprovalEvent.STATE_REJECT; - EventPusher.push(new FlowApprovalEvent(eventState, flowRecord, currentOperator, flowWork, snapshot.toBindData())); + EventPusher.push(new FlowApprovalEvent(eventState, flowRecord, currentOperator, flowWork, snapshot.toBindData()),true); // 推送待办事件消息 for (FlowRecord record : records) { IFlowOperator pushOperator = record.getCurrentOperator(); - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, record, pushOperator, flowWork, snapshot.toBindData())); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, record, pushOperator, flowWork, snapshot.toBindData()),true); } return new FlowResult(flowWork, records); @@ -516,7 +516,7 @@ public void recall(long recordId, IFlowOperator currentOperator) { flowRecordRepository.update(flowRecord); flowRecordRepository.delete(childrenRecords); - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_RECALL, flowRecord, currentOperator, flowWork, null)); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_RECALL, flowRecord, currentOperator, flowWork, null),true); } } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 5fcce435..684ba48a 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.1 + 2.9.2 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 7291503a..c2a21b2c 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.1 + 2.9.2 springboot-starter From 5cf9a37b837490aa58e42d8bfb7980b4006c83a6 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 9 Nov 2024 20:40:37 +0800 Subject: [PATCH 057/129] add event error logs --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../springboot/framework/exception/EventException.java | 3 +++ 6 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 593898fb..de1eedf5 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.2 + 2.9.3.1 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 773213a8..5ea6f609 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.2 + 2.9.3.1 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 92e666e4..8c7a9b08 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.2 + 2.9.3.1 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 684ba48a..9c55e0dd 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.2 + 2.9.3.1 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index c2a21b2c..d583065a 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.2 + 2.9.3.1 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java index 68462e73..5a506fec 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java @@ -13,5 +13,8 @@ public class EventException extends RuntimeException { public EventException(List error) { super(error.stream().map(Exception::getMessage).collect(Collectors.joining("\n"))); this.error = error; + for (Exception e : error) { + e.printStackTrace(); + } } } From 70241e9d939cec8b65645b3f990841b3b0cac3a2 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 12 Nov 2024 21:24:44 +0800 Subject: [PATCH 058/129] SecurityLoginHandler add UserDetails --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- .../springboot/security/AutoConfiguration.java | 2 +- .../security/filter/MyLoginFilter.java | 17 ++++++++++++++--- .../security/filter/SecurityLoginHandler.java | 3 ++- springboot-starter/pom.xml | 2 +- 8 files changed, 22 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index de1eedf5..247866dc 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.3.1 + 2.9.4 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 5ea6f609..1e5d7744 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.3.1 + 2.9.4 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 8c7a9b08..0581c28f 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.3.1 + 2.9.4 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 9c55e0dd..557f7bc5 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.3.1 + 2.9.4 springboot-starter-security diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java index 339ae029..b60f597c 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java @@ -78,7 +78,7 @@ public void preHandle(HttpServletRequest request, HttpServletResponse response, } @Override - public LoginResponse postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest loginRequest, Token token) { + public LoginResponse postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest loginRequest,UserDetails userDetails, Token token) { LoginResponse loginResponse = new LoginResponse(); loginResponse.setUsername(token.getUsername()); loginResponse.setToken(token.getToken()); diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java index 4f2939be..c0ecc62b 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java @@ -18,7 +18,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @@ -69,16 +69,21 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { log.debug("login success authentication ~"); - User user = (User) authResult.getPrincipal(); + UserDetails user = (UserDetails) authResult.getPrincipal(); LoginRequest loginRequest = LoginRequestContext.getInstance().get(); Token token = tokenGateway.create(user.getUsername(), loginRequest.getPassword(), user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()), TokenContext.getExtra()); - LoginResponse loginResponse = loginHandler.postHandle(request, response, loginRequest, token); + LoginResponse loginResponse = loginHandler.postHandle(request, response, loginRequest, user, token); String content = JSONObject.toJSONString(SingleResponse.of(loginResponse)); + + // 设置响应的 Content-Type 为 JSON,并指定字符编码为 UTF-8 + response.setContentType("application/json;charset=UTF-8"); + response.setCharacterEncoding("UTF-8"); + IOUtils.write(content, response.getOutputStream(), StandardCharsets.UTF_8); LoginRequestContext.getInstance().clean(); @@ -89,7 +94,13 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { log.debug("login fail authentication ~"); String content = JSONObject.toJSONString(Response.buildFailure("login.error", failed.getMessage())); + + // 设置响应的 Content-Type 为 JSON,并指定字符编码为 UTF-8 + response.setContentType("application/json;charset=UTF-8"); + response.setCharacterEncoding("UTF-8"); + IOUtils.write(content, response.getOutputStream(), StandardCharsets.UTF_8); + LoginRequestContext.getInstance().clean(); } } diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java index ed0b5876..db7bc687 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java @@ -3,6 +3,7 @@ import com.codingapi.springboot.security.dto.request.LoginRequest; import com.codingapi.springboot.security.dto.response.LoginResponse; import com.codingapi.springboot.security.gateway.Token; +import org.springframework.security.core.userdetails.UserDetails; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -12,5 +13,5 @@ public interface SecurityLoginHandler { void preHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest loginRequest) throws Exception; - LoginResponse postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest loginRequest, Token token); + LoginResponse postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest loginRequest, UserDetails userDetails, Token token); } diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index d583065a..f0894754 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.3.1 + 2.9.4 springboot-starter From 5fcb38ed771295b21c6cb94a9c74137deb0b84a1 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 12 Nov 2024 21:28:14 +0800 Subject: [PATCH 059/129] SecurityLoginHandler add UserDetails --- .../springboot/security/filter/MyAccessDeniedHandler.java | 4 ++++ .../springboot/security/filter/MyAuthenticationFilter.java | 4 ++++ .../springboot/security/filter/MyLogoutSuccessHandler.java | 4 ++++ .../security/filter/MyUnAuthenticationEntryPoint.java | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java index 4387a65b..beb79203 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAccessDeniedHandler.java @@ -20,6 +20,10 @@ public class MyAccessDeniedHandler implements AccessDeniedHandler { public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { log.debug("access denied"); String content = JSONObject.toJSONString(Response.buildFailure("not.access", "please check user authentication.")); + // 设置响应的 Content-Type 为 JSON,并指定字符编码为 UTF-8 + response.setContentType("application/json;charset=UTF-8"); + response.setCharacterEncoding("UTF-8"); + IOUtils.write(content, response.getOutputStream(), StandardCharsets.UTF_8); } } diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java index ed73501b..232fd938 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java @@ -75,6 +75,10 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse private void writeResponse(HttpServletResponse servletResponse, Response returnResponse) throws IOException { String content = JSONObject.toJSONString(returnResponse); + // 设置响应的 Content-Type 为 JSON,并指定字符编码为 UTF-8 + servletResponse.setContentType("application/json;charset=UTF-8"); + servletResponse.setCharacterEncoding("UTF-8"); + IOUtils.write(content, servletResponse.getOutputStream(), StandardCharsets.UTF_8); } diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java index 7ed35833..5b6520a6 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java @@ -20,6 +20,10 @@ public class MyLogoutSuccessHandler implements LogoutSuccessHandler { public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { log.debug("logout success ~"); String content = JSONObject.toJSONString(Response.buildSuccess()); + // 设置响应的 Content-Type 为 JSON,并指定字符编码为 UTF-8 + response.setContentType("application/json;charset=UTF-8"); + response.setCharacterEncoding("UTF-8"); + IOUtils.write(content, response.getOutputStream(), StandardCharsets.UTF_8); } } diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java index c1e610f8..885b6241 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyUnAuthenticationEntryPoint.java @@ -21,6 +21,10 @@ public class MyUnAuthenticationEntryPoint implements AuthenticationEntryPoint { public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { log.debug("no authentication ~"); String content = JSONObject.toJSONString(Response.buildFailure("not.login", "please to login.")); + // 设置响应的 Content-Type 为 JSON,并指定字符编码为 UTF-8 + response.setContentType("application/json;charset=UTF-8"); + response.setCharacterEncoding("UTF-8"); + IOUtils.write(content, response.getOutputStream(), StandardCharsets.UTF_8); } } From ac75bb8c60e2d0f8d42d8fc13a6e5fbb7ce29451 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 13 Nov 2024 21:11:37 +0800 Subject: [PATCH 060/129] add SQLBuilder --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../springboot/fast/jdbc/JdbcQuery.java | 29 ++++++++-- .../springboot/fast/jpa/JPAQuery.java | 13 ++++- .../springboot/fast/jpa/SQLBuilder.java | 55 +++++++++++++++++++ .../repository/DynamicNativeRepository.java | 27 +++++++-- .../jpa/repository/DynamicRepository.java | 11 +++- .../springboot/fast/DemoRepositoryTest.java | 47 ++++++++++++++-- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 11 files changed, 167 insertions(+), 25 deletions(-) create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java diff --git a/pom.xml b/pom.xml index 247866dc..89c2678d 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.4 + 2.9.5 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 1e5d7744..ae8091cb 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.4 + 2.9.5 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java index d20e379c..0a3e8be0 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java @@ -1,5 +1,6 @@ package com.codingapi.springboot.fast.jdbc; +import com.codingapi.springboot.fast.jpa.SQLBuilder; import org.apache.commons.text.CaseUtils; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -37,14 +38,26 @@ public Map mapRow(ResultSet rs, int rowNum) throws SQLException } } - public List> queryForList(String sql, Object... params) { + public List> queryForMapList(SQLBuilder builder) { + return queryForMapList(builder.getSQL(), builder.getParams()); + } + + public List> queryForMapList(String sql, Object... params) { return jdbcTemplate.query(sql, params, new CamelCaseRowMapper()); } + public List queryForList(SQLBuilder builder) { + return (List) queryForList(builder.getSQL(), builder.getClazz(), builder.getParams()); + } + public List queryForList(String sql, Class clazz, Object... params) { return jdbcTemplate.query(sql, params, new BeanPropertyRowMapper<>(clazz)); } + public Page queryForPage(SQLBuilder builder, PageRequest pageRequest) { + return (Page)queryForPage(builder.getSQL(), builder.getCountSQL(), builder.getClazz(), pageRequest, builder.getParams()); + } + public Page queryForPage(String sql, String countSql, Class clazz, PageRequest pageRequest, Object... params) { List list = jdbcTemplate.query(sql, params, new BeanPropertyRowMapper<>(clazz)); long count = this.countQuery(countSql, params); @@ -52,19 +65,23 @@ public Page queryForPage(String sql, String countSql, Class clazz, Pag } public Page queryForPage(String sql, Class clazz, PageRequest pageRequest, Object... params) { - String countSql = "select count(1) "+sql; + String countSql = "select count(1) " + sql; return this.queryForPage(sql, countSql, clazz, pageRequest, params); } - public Page> queryForPage(String sql, String countSql, PageRequest pageRequest, Object... params) { + public Page> queryForMapPage(SQLBuilder builder, PageRequest pageRequest) { + return queryForMapPage(builder.getSQL(), builder.getCountSQL(), pageRequest, builder.getParams()); + } + + public Page> queryForMapPage(String sql, String countSql, PageRequest pageRequest, Object... params) { List> list = jdbcTemplate.query(sql, params, new CamelCaseRowMapper()); long count = this.countQuery(countSql, params); return new PageImpl<>(list, pageRequest, count); } - public Page> queryForPage(String sql, PageRequest pageRequest, Object... params) { - String countSql = "select count(1) "+sql; - return this.queryForPage(sql, countSql, pageRequest, params); + public Page> queryForMapPage(String sql, PageRequest pageRequest, Object... params) { + String countSql = "select count(1) " + sql; + return this.queryForMapPage(sql, countSql, pageRequest, params); } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java index 6342af68..aa1ddaff 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java @@ -1,12 +1,12 @@ package com.codingapi.springboot.fast.jpa; -import javax.persistence.EntityManager; -import javax.persistence.TypedQuery; import lombok.AllArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; import java.util.List; @AllArgsConstructor @@ -14,6 +14,10 @@ public class JPAQuery { private final EntityManager entityManager; + public List listQuery(SQLBuilder builder) { + return listQuery(builder.getClazz(),builder.getSQL(),builder.getParams()); + } + public List listQuery(Class clazz, String sql, Object... params) { TypedQuery query = entityManager.createQuery(sql, clazz); if (params != null) { @@ -24,6 +28,11 @@ public List listQuery(Class clazz, String sql, Object... params) { return query.getResultList(); } + public Page pageQuery(SQLBuilder builder,PageRequest pageRequest) { + return pageQuery(builder.getClazz(), builder.getSQL(), builder.getCountSQL(),pageRequest,builder.getParams()); + } + + public Page pageQuery(Class clazz, String sql, PageRequest pageRequest, Object... params) { return pageQuery(clazz,sql,"select count(1) " + sql,pageRequest,params); } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java new file mode 100644 index 00000000..0eaaf2e4 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java @@ -0,0 +1,55 @@ +package com.codingapi.springboot.fast.jpa; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +public class SQLBuilder { + + private final StringBuilder sqlBuilder; + private final StringBuilder countSQLBuilder; + private int index; + private final List params; + @Getter + private final Class clazz; + + public SQLBuilder(String sql) { + this(null, sql, "select count(1) from " + sql); + } + + public SQLBuilder(Class clazz, String sql) { + this(clazz, sql, "select count(1) from " + sql); + } + + public SQLBuilder(Class clazz, String sql, String countSQL) { + this.countSQLBuilder = new StringBuilder(countSQL); + this.sqlBuilder = new StringBuilder(sql); + this.index = 1; + this.params = new ArrayList<>(); + this.clazz = clazz; + } + + public void append(String sql, Object value) { + if (value != null) { + sqlBuilder.append(" ").append(sql).append(index).append(" "); + countSQLBuilder.append(" ").append(sql).append(index).append(" "); + params.add(value); + index++; + } + } + + public String getSQL() { + return sqlBuilder.toString(); + } + + public String getCountSQL() { + return countSQLBuilder.toString(); + } + + public Object[] getParams() { + return params.toArray(); + } + + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java index 1dd846b9..7641a488 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java @@ -1,6 +1,7 @@ package com.codingapi.springboot.fast.jpa.repository; import com.codingapi.springboot.fast.jdbc.JdbcQueryContext; +import com.codingapi.springboot.fast.jpa.SQLBuilder; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.repository.NoRepositoryBean; @@ -11,8 +12,12 @@ @NoRepositoryBean public interface DynamicNativeRepository extends BaseRepository { + default List> dynamicNativeListMapQuery(SQLBuilder builder) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForMapList(builder); + } + default List> dynamicNativeListMapQuery(String sql, Object... params) { - return JdbcQueryContext.getInstance().getJdbcQuery().queryForList(sql, params); + return JdbcQueryContext.getInstance().getJdbcQuery().queryForMapList(sql, params); } default List dynamicNativeListQuery(String sql, Object... params) { @@ -23,6 +28,10 @@ default List dynamicNativeListQuery(Class clazz, String sql, Object... return JdbcQueryContext.getInstance().getJdbcQuery().queryForList(sql, clazz, params); } + default List dynamicNativeListQuery(SQLBuilder sqlBuilder) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForList(sqlBuilder); + } + default Page dynamicNativePageQuery(String sql, String countSql, PageRequest request, Object... params) { return dynamicNativePageQuery(getEntityClass(), sql, countSql, request, params); } @@ -39,12 +48,20 @@ default Page dynamicNativePageQuery(Class clazz, String sql, PageReque return JdbcQueryContext.getInstance().getJdbcQuery().queryForPage(sql, clazz, request, params); } - default Page> dynamicNativePageMapQuery(String sql, String countSql, PageRequest request, Object... params) { - return JdbcQueryContext.getInstance().getJdbcQuery().queryForPage(sql, countSql, request, params); + default Page dynamicNativePageQuery(SQLBuilder sqlBuilder, PageRequest request) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForPage(sqlBuilder, request); + } + + default Page> dynamicNativeMapPageMapQuery(SQLBuilder sqlBuilder,PageRequest request) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForMapPage(sqlBuilder,request); + } + + default Page> dynamicNativeMapPageMapQuery(String sql, String countSql, PageRequest request, Object... params) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForMapPage(sql, countSql, request, params); } - default Page> dynamicNativePageMapQuery(String sql, PageRequest request, Object... params) { - return JdbcQueryContext.getInstance().getJdbcQuery().queryForPage(sql, request, params); + default Page> dynamicNativeMapPageMapQuery(String sql, PageRequest request, Object... params) { + return JdbcQueryContext.getInstance().getJdbcQuery().queryForMapPage(sql, request, params); } } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java index b8e0850c..a2fe6c76 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java @@ -1,6 +1,7 @@ package com.codingapi.springboot.fast.jpa.repository; import com.codingapi.springboot.fast.jpa.JpaQueryContext; +import com.codingapi.springboot.fast.jpa.SQLBuilder; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.repository.NoRepositoryBean; @@ -11,6 +12,10 @@ @SuppressWarnings("unchecked") public interface DynamicRepository extends BaseRepository { + default List dynamicListQuery(SQLBuilder builder) { + return (List) JpaQueryContext.getInstance().getJPAQuery().listQuery(builder); + } + default List dynamicListQuery(String sql, Object... params) { return (List) JpaQueryContext.getInstance().getJPAQuery().listQuery(getEntityClass(), sql, params); } @@ -19,12 +24,16 @@ default List dynamicListQuery(Class clazz, String sql, Object... param return (List) JpaQueryContext.getInstance().getJPAQuery().listQuery(clazz, sql, params); } + default Page dynamicPageQuery(SQLBuilder builder, PageRequest request) { + return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(builder, request); + } + default Page dynamicPageQuery(String sql, String countSql, PageRequest request, Object... params) { return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, countSql, request, params); } default Page dynamicPageQuery(String sql, PageRequest request, Object... params) { - return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, request, params); + return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, request, params); } default Page dynamicPageQuery(Class clazz, String sql, String countSql, PageRequest request, Object... params) { diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index 9b2ec82a..cb2ea09b 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -1,6 +1,7 @@ package com.codingapi.springboot.fast; import com.codingapi.springboot.fast.entity.Demo; +import com.codingapi.springboot.fast.jpa.SQLBuilder; import com.codingapi.springboot.fast.repository.DemoRepository; import com.codingapi.springboot.framework.dto.request.Filter; import com.codingapi.springboot.framework.dto.request.PageRequest; @@ -47,7 +48,7 @@ void findAll() { demoRepository.save(demo2); PageRequest request = new PageRequest(); - request.setCurrent(0); + request.setCurrent(1); request.setPageSize(10); request.addFilter("name", "123"); @@ -68,7 +69,7 @@ void pageRequest() { demoRepository.save(demo2); PageRequest request = new PageRequest(); - request.setCurrent(0); + request.setCurrent(1); request.setPageSize(10); request.addFilter("name", Relation.LIKE, "%2%"); @@ -89,7 +90,7 @@ void customInSearch() { demoRepository.save(demo2); PageRequest request = new PageRequest(); - request.setCurrent(0); + request.setCurrent(1); request.setPageSize(10); request.addFilter("id", Relation.IN, 1, 2, 3); @@ -116,7 +117,12 @@ void customOrSearch() { request.setPageSize(10); - request.orFilters(Filter.as("id", Relation.IN, 1, 2, 3), Filter.as("name", "123")); +// request.andFilter(Filter.as("id", Relation.IN, 1, 2, 3), Filter.as("name", "123")); + request.addFilter("name", "456").orFilters(Filter.as("id", Relation.IN, 1, 2, 3), Filter.as("name", "123")); + + request.addSort(Sort.by("id").descending()); + + Page page = demoRepository.pageRequest(request); log.info("demo:{}", page.getContent()); @@ -134,7 +140,32 @@ void dynamicListQuery() { demo2.setName("456"); demoRepository.save(demo2); - List list = demoRepository.dynamicListQuery("from Demo where name = ?1", "123"); + SQLBuilder builder = new SQLBuilder(Demo.class,"from Demo where 1=1"); + String search = "12"; + builder.append("and name like ?","%"+search+"%"); + + List list = demoRepository.dynamicListQuery(builder); + assertEquals(1, list.size()); + } + + + + @Test + void dynamicNativeListQuery() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + SQLBuilder builder = new SQLBuilder(Demo.class,"select * from t_demo where 1=1"); + String search = "12"; + builder.append("and name like ?","%"+search+"%"); + + List list = demoRepository.dynamicNativeListQuery(builder); assertEquals(1, list.size()); } @@ -150,7 +181,11 @@ void dynamicPageQuery() { demo2.setName("456"); demoRepository.save(demo2); - Page page = demoRepository.dynamicPageQuery("from Demo where name = ?1", PageRequest.of(1, 2), "123"); + SQLBuilder builder = new SQLBuilder(Demo.class,"select d from Demo d where 1=1","select count(1) from Demo d where 1=1"); + String search = "12"; + builder.append("and d.name like ?","%"+search+"%"); + + Page page = demoRepository.dynamicPageQuery(builder,PageRequest.of(1, 2)); assertEquals(1, page.getTotalElements()); } diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 0581c28f..a08e272c 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.4 + 2.9.5 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 557f7bc5..f65d1323 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.4 + 2.9.5 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index f0894754..8fd9e8f8 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.4 + 2.9.5 springboot-starter From 7bf1a12fe9b418616c7306a2a431d91e3a519e45 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 15 Nov 2024 09:51:39 +0800 Subject: [PATCH 061/129] add FlowRecord workCode --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/domain/FlowNode.java | 3 ++ .../flow/query/FlowRecordQuery.java | 42 +++++++++++++++ .../springboot/flow/record/FlowRecord.java | 7 +++ .../service/FlowRecordBuilderService.java | 6 +-- .../springboot/flow/service/FlowService.java | 1 + .../repository/FlowRecordRepositoryImpl.java | 52 +++++++++++++++++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 11 files changed, 113 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 89c2678d..f67cfd10 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.5 + 2.9.6 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index ae8091cb..79dbc8cb 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.5 + 2.9.6 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index a08e272c..cbd1aee6 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.5 + 2.9.6 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java index 7d9291ed..2084a4f6 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java @@ -179,6 +179,7 @@ public List loadFlowNodeOperator(FlowSession flowSessio * 创建流程记录 * * @param workId 流程设计id + * @param workCode 流程设计编码 * @param processId 流程id * @param preId 上一条流程记录id * @param title 流程标题 @@ -188,6 +189,7 @@ public List loadFlowNodeOperator(FlowSession flowSessio * @return 流程记录 */ public FlowRecord createRecord(long workId, + String workCode, String processId, long preId, String title, @@ -207,6 +209,7 @@ public FlowRecord createRecord(long workId, record.setNodeCode(this.code); record.setCreateTime(System.currentTimeMillis()); record.setWorkId(workId); + record.setWorkCode(workCode); record.setFlowStatus(FlowStatus.RUNNING); record.setPostponedCount(0); record.setCreateOperator(createOperator); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java index de2e4298..79e372dc 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java @@ -21,6 +21,16 @@ public interface FlowRecordQuery { Page findTodoByOperatorId(long operatorId, PageRequest pageRequest); + /** + * 查看个人的待办数据(指定流程) + * + * @param operatorId 操作人 + * @param workCode 流程编码 + * @return 流程记录 + */ + Page findTodoByOperatorId(long operatorId,String workCode, PageRequest pageRequest); + + /** * 查看个人的已办数据 * @param operatorId 操作人 @@ -29,6 +39,14 @@ public interface FlowRecordQuery { Page findDoneByOperatorId(long operatorId, PageRequest pageRequest); + /** + * 查看个人的已办数据 (指定流程) + * @param operatorId 操作人 + * @param workCode 流程编码 + * @return 流程记录 + */ + Page findDoneByOperatorId(long operatorId,String workCode, PageRequest pageRequest); + /** * 查看个人的发起数据 (含待办与已办) * @param operatorId 操作人 @@ -37,6 +55,14 @@ public interface FlowRecordQuery { Page findInitiatedByOperatorId(long operatorId, PageRequest pageRequest); + /** + * 查看个人的发起数据 (含待办与已办、指定流程) + * @param operatorId 操作人 + * @param workCode 流程编码 + * @return 流程记录 + */ + Page findInitiatedByOperatorId(long operatorId,String workCode, PageRequest pageRequest); + /** * 查看个人的超时的待办流程 * @param operatorId 操作人 @@ -44,6 +70,13 @@ public interface FlowRecordQuery { */ Page findTimeoutTodoByOperatorId(long operatorId, PageRequest pageRequest); + /** + * 查看个人的超时的待办流程 (指定流程) + * @param operatorId 操作人 + * @param workCode 流程编码 + * @return 流程记录 + */ + Page findTimeoutTodoByOperatorId(long operatorId,String workCode, PageRequest pageRequest); /** * 查看个人的延期的待办流程 @@ -52,4 +85,13 @@ public interface FlowRecordQuery { */ Page findPostponedTodoByOperatorId(long operatorId, PageRequest pageRequest); + + /** + * 查看个人的延期的待办流程 + * @param operatorId 操作人 + * @param workCode 流程编码 + * @return 流程记录 + */ + Page findPostponedTodoByOperatorId(long operatorId,String workCode, PageRequest pageRequest); + } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java index 41a57d1b..fa96ce9b 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -33,6 +33,12 @@ public class FlowRecord { * 工作id */ private long workId; + + /** + * 流程编码 + */ + private String workCode; + /** * 流程id */ @@ -367,6 +373,7 @@ public FlowRecord copy() { record.setPostponedCount(this.postponedCount); record.setPreId(this.preId); record.setWorkId(this.workId); + record.setWorkCode(this.workCode); record.setProcessId(this.processId); record.setNodeCode(this.nodeCode); record.setTitle(this.title); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordBuilderService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordBuilderService.java index 654ef87a..9d4f812a 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordBuilderService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordBuilderService.java @@ -120,7 +120,7 @@ private List errMatcher(FlowNode currentNode, IFlowOperator currentO for (IFlowOperator operator : operators) { FlowSession content = new FlowSession(flowWork, currentNode, createOperator, operator, snapshot.toBindData(), opinion, historyRecords); String recordTitle = currentNode.generateTitle(content); - FlowRecord record = currentNode.createRecord(flowWork.getId(), processId, preId, recordTitle, createOperator, operator, snapshot); + FlowRecord record = currentNode.createRecord(flowWork.getId(),flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot); recordList.add(record); } return recordList; @@ -138,7 +138,7 @@ private List errMatcher(FlowNode currentNode, IFlowOperator currentO if (!matcherOperators.isEmpty()) { for (IFlowOperator matcherOperator : matcherOperators) { String recordTitle = node.generateTitle(content); - FlowRecord record = node.createRecord(flowWork.getId(), processId, preId, recordTitle, createOperator, matcherOperator, snapshot); + FlowRecord record = node.createRecord(flowWork.getId(),flowWork.getCode(), processId, preId, recordTitle, createOperator, matcherOperator, snapshot); recordList.add(record); } } @@ -182,7 +182,7 @@ public List createRecord(FlowNode currentNode, IFlowOperator current String recordTitle = currentNode.generateTitle(flowSession); recordList = new ArrayList<>(); for (IFlowOperator operator : operators) { - FlowRecord record = currentNode.createRecord(workId, processId, preId, recordTitle, createOperator, operator, snapshot); + FlowRecord record = currentNode.createRecord(workId,flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot); recordList.add(record); } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index a38930a6..6bb0d65d 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -20,6 +20,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java index 5875e22d..36cfde5c 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java @@ -43,6 +43,8 @@ public List findFlowRecordByPreId(long preId) { return cache.stream().filter(record -> record.getPreId() == preId).collect(Collectors.toList()); } + + @Override public List findFlowRecordByProcessId(String processId) { return cache.stream().filter(record -> record.getProcessId().equals(processId)) @@ -59,24 +61,52 @@ public Page findAll(PageRequest pageRequest) { return new PageImpl<>(cache); } + @Override public Page findDoneByOperatorId(long operatorId,PageRequest pageRequest) { List flowRecords = cache.stream().filter(record -> record.isDone() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); return new PageImpl<>(flowRecords); } + @Override + public Page findDoneByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { + List flowRecords = cache.stream().filter(record -> record.isDone() + && record.getCurrentOperator().getUserId() == operatorId + && record.getWorkCode().equals(workCode) + ).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + @Override public Page findInitiatedByOperatorId(long operatorId,PageRequest pageRequest) { List flowRecords = cache.stream().filter(record -> record.isInitiated() && record.getCreateOperator().getUserId() == operatorId).collect(Collectors.toList()); return new PageImpl<>(flowRecords); } + + @Override + public Page findInitiatedByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { + List flowRecords = cache.stream().filter( + record -> record.isInitiated() + && record.getCreateOperator().getUserId() == operatorId + && record.getWorkCode().equals(workCode) + ).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + + @Override public Page findTodoByOperatorId(long operatorId,PageRequest pageRequest) { List flowRecords = cache.stream().filter(record -> record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); return new PageImpl<>(flowRecords); } + @Override + public Page findTodoByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { + List flowRecords = cache.stream().filter(record -> record.isTodo() && record.getCurrentOperator().getUserId() == operatorId && record.getWorkCode().equals(workCode)).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + @Override public Page findTimeoutTodoByOperatorId(long operatorId,PageRequest pageRequest) { List flowRecords = cache.stream().filter(record -> record.isTimeout() && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); @@ -84,12 +114,34 @@ public Page findTimeoutTodoByOperatorId(long operatorId,PageRequest } + + @Override + public Page findTimeoutTodoByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { + List flowRecords = cache.stream().filter( + record -> record.isTimeout() + && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId + && record.getWorkCode().equals(workCode) + ).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + + @Override public Page findPostponedTodoByOperatorId(long operatorId,PageRequest pageRequest) { List flowRecords = cache.stream().filter(record -> record.isPostponed() && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); return new PageImpl<>(flowRecords); } + + @Override + public Page findPostponedTodoByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { + List flowRecords = cache.stream().filter(record -> record.isPostponed() + && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId + && record.getWorkCode().equals(workCode) + ).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + @Override public void finishFlowRecordByProcessId(String processId) { cache.stream() diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index f65d1323..62c748bd 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.5 + 2.9.6 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 8fd9e8f8..e1440db2 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.5 + 2.9.6 springboot-starter From adcd6b8641f90929ff02c7a0a5e2bba2dbe0e928 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 5 Dec 2024 23:53:56 +0800 Subject: [PATCH 062/129] update flow --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../jpa/repository/DynamicSQLBuilder.java | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/bind/IBindData.java | 9 + .../flow/build/FlowWorkBuilder.java | 43 +- .../springboot/flow/build/SchemaReader.java | 31 +- .../springboot/flow/content/FlowSession.java | 143 ++++- .../springboot/flow/domain/FlowButton.java | 78 +++ .../springboot/flow/domain/FlowNode.java | 34 +- .../springboot/flow/domain/FlowWork.java | 1 + .../springboot/flow/domain/Opinion.java | 32 ++ .../springboot/flow/em/ApprovalType.java | 6 +- .../springboot/flow/em/FlowButtonType.java | 29 + .../flow/em/FlowSourceDirection.java | 8 +- .../springboot/flow/em/FlowType.java | 4 + .../springboot/flow/em/NodeType.java | 4 + .../flow/event/FlowApprovalEvent.java | 2 + .../flow/matcher/OperatorMatcher.java | 1 - .../springboot/flow/pojo/FlowDetail.java | 28 +- .../flow/pojo/FlowSubmitResult.java | 23 + .../flow/query/FlowRecordQuery.java | 19 + .../springboot/flow/record/FlowRecord.java | 11 + .../repository/FlowProcessRepository.java | 2 +- .../flow/repository/FlowRecordRepository.java | 6 +- .../springboot/flow/result/MessageResult.java | 138 +++++ .../springboot/flow/result/ResultState.java | 23 + .../serializable/FlowNodeSerializable.java | 8 +- .../serializable/FlowWorkSerializable.java | 13 +- .../flow/service/FlowDirectionService.java | 4 +- ...ilderService.java => FlowNodeService.java} | 317 +++++++---- ...vice.java => FlowRecordVerifyService.java} | 14 +- .../springboot/flow/service/FlowService.java | 506 ++++-------------- .../service/impl/FlowCustomEventService.java | 76 +++ .../flow/service/impl/FlowDetailService.java | 114 ++++ .../service/impl/FlowPostponedService.java | 44 ++ .../flow/service/impl/FlowRecallService.java | 73 +++ .../flow/service/impl/FlowSaveService.java | 51 ++ .../flow/service/impl/FlowStartService.java | 142 +++++ .../flow/service/impl/FlowSubmitService.java | 196 +++++++ .../service/impl/FlowTransferService.java | 100 ++++ .../service/impl/FlowTrySubmitService.java | 250 +++++++++ .../flow/service/impl/FlowUrgeService.java | 50 ++ .../repository/FlowRecordRepositoryImpl.java | 26 +- .../springboot/flow/test/BuildTest.java | 9 +- .../springboot/flow/test/CirculateTest.java | 138 +++++ .../springboot/flow/test/ErrorTest.java | 26 +- .../springboot/flow/test/FlowTest.java | 156 ++++-- .../springboot/flow/test/FlowTest2.java | 7 +- .../flow/test/MultiRelationFlowTest.java | 36 +- .../springboot/flow/test/QueryTest.java | 71 +-- .../springboot/flow/test/ScriptBuildTest.java | 9 +- .../springboot/flow/test/ScriptTest.java | 2 +- .../springboot/flow/test/SignTest.java | 39 +- .../springboot/flow/test/TrySubmitTest.java | 134 +++++ springboot-starter-security/pom.xml | 2 +- .../security/filter/MyLoginFilter.java | 2 +- springboot-starter/pom.xml | 2 +- 58 files changed, 2555 insertions(+), 745 deletions(-) create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowButton.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowButtonType.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowSubmitResult.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/result/MessageResult.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/result/ResultState.java rename springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/{FlowRecordBuilderService.java => FlowNodeService.java} (53%) rename springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/{FlowRecordService.java => FlowRecordVerifyService.java} (91%) create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowCustomEventService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowPostponedService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTransferService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowUrgeService.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/CirculateTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/TrySubmitTest.java diff --git a/pom.xml b/pom.xml index f67cfd10..f9d62149 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.6 + 2.9.7 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 79dbc8cb..b2efbee5 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.6 + 2.9.7 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java index caa1a9d7..eb2a15c8 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java @@ -45,7 +45,7 @@ public String getHQL() { Sort sort = request.getSort(); if (sort.isSorted()) { hql.append(" ORDER BY "); - List orders = sort.toList(); + List orders = sort.collect(Collectors.toList()); for (int i = 0; i < orders.size(); i++) { Sort.Order order = orders.get(i); hql.append(order.getProperty()).append(" ").append(order.getDirection().name()); diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index cbd1aee6..4aac3f3a 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.6 + 2.9.7 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java index 6a7287bc..4814cdcb 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java @@ -15,4 +15,13 @@ public interface IBindData { default String toJsonSnapshot() { return JSONObject.toJSONString(this); } + + + /** + * 获取类名称 + * @return 类名称 + */ + default String getClazzName() { + return this.getClass().getName(); + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java index 08d89bf5..2749b7cf 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java @@ -1,5 +1,6 @@ package com.codingapi.springboot.flow.build; +import com.codingapi.springboot.flow.domain.FlowButton; import com.codingapi.springboot.flow.domain.FlowNode; import com.codingapi.springboot.flow.domain.FlowRelation; import com.codingapi.springboot.flow.domain.FlowWork; @@ -12,6 +13,8 @@ import com.codingapi.springboot.flow.user.IFlowOperator; import com.codingapi.springboot.framework.utils.RandomGenerator; +import java.util.List; + /** * 流程工作构建器 */ @@ -65,25 +68,43 @@ public FlowWork build() { public class Nodes { - public Nodes node(String id,String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, TitleGenerator titleGenerator, ErrTrigger errTrigger, boolean editable) { - FlowNode node = new FlowNode(id, name, code, view, NodeType.parser(code), approvalType, titleGenerator, operatorMatcher, timeout, errTrigger, editable); + public Nodes node(String id, String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, TitleGenerator titleGenerator, ErrTrigger errTrigger, boolean editable, List buttons) { + FlowNode node = new FlowNode(id, name, code, view, NodeType.parser(code), approvalType, titleGenerator, operatorMatcher, timeout, errTrigger, editable, buttons); work.addNode(node); return this; } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher,long timeout, boolean editable) { - return node(RandomGenerator.generateUUID(),name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, boolean editable) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable, null); + } + + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, boolean editable, List buttons) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable, buttons); } + + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, boolean editable) { - return node(RandomGenerator.generateUUID(),name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable); + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable, null); + } + + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, boolean editable, List buttons) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable, buttons); + } + + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, List buttons) { + return node(name, code, view, approvalType, operatorMatcher, true, buttons); } public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher) { - return node(name, code, view, approvalType, operatorMatcher, true); + return node(name, code, view, approvalType, operatorMatcher, true, null); + } + + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable, List buttons) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable, buttons); } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable) { - return node(RandomGenerator.generateUUID(),name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable, null); } @@ -102,13 +123,13 @@ public FlowWork build() { public class Relations { public Relations relation(String name, String source, String target) { - return relation(name,source,target,OutTrigger.defaultOutTrigger(),1,false); + return relation(name, source, target, OutTrigger.defaultOutTrigger(), 1, false); } - public Relations relation(String name, String source, String target, OutTrigger outTrigger,int order, boolean back) { + public Relations relation(String name, String source, String target, OutTrigger outTrigger, int order, boolean back) { FlowNode from = work.getNodeByCode(source); FlowNode to = work.getNodeByCode(target); - FlowRelation relation = new FlowRelation(RandomGenerator.generateUUID(), name, from, to, outTrigger,order, back); + FlowRelation relation = new FlowRelation(RandomGenerator.generateUUID(), name, from, to, outTrigger, order, back); work.addRelation(relation); return this; } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java index bb5abd75..f169b75e 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java @@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.codingapi.springboot.flow.domain.FlowButton; import com.codingapi.springboot.flow.domain.FlowNode; import com.codingapi.springboot.flow.domain.FlowRelation; import com.codingapi.springboot.flow.em.ApprovalType; @@ -37,7 +38,7 @@ public SchemaReader(String schema) { } - private void loadNodes(){ + private void loadNodes() { JSONArray nodes = data.getJSONArray("nodes"); for (int i = 0; i < nodes.size(); i++) { JSONObject node = nodes.getJSONObject(i); @@ -53,39 +54,43 @@ private void loadNodes(){ int timeout = properties.getIntValue("timeout"); String errTrigger = properties.getString("errTrigger"); String id = properties.getString("id"); - FlowNode flowNode = new FlowNode(id,name,code,view, NodeType.parser(type),ApprovalType.parser(approvalType),new TitleGenerator(titleGenerator), - new OperatorMatcher(operatorMatcher),timeout, StringUtils.hasLength(errTrigger)?new ErrTrigger(errTrigger):null,editable); + List buttons = null; + if(properties.containsKey("buttons")){ + buttons = properties.getJSONArray("buttons").toJavaList(FlowButton.class); + } + FlowNode flowNode = new FlowNode(id, name, code, view, NodeType.parser(type), ApprovalType.parser(approvalType), new TitleGenerator(titleGenerator), + new OperatorMatcher(operatorMatcher), timeout, StringUtils.hasLength(errTrigger) ? new ErrTrigger(errTrigger) : null, editable, buttons); flowNodes.add(flowNode); } } - private FlowNode getFlowNodeById(String id){ - for(FlowNode flowNode:flowNodes){ - if(flowNode.getId().equals(id)){ + private FlowNode getFlowNodeById(String id) { + for (FlowNode flowNode : flowNodes) { + if (flowNode.getId().equals(id)) { return flowNode; } } return null; } - private void loadEdges(){ + private void loadEdges() { JSONArray edges = data.getJSONArray("edges"); - for(int i=0;i historyRecords; + // bean提供者 private final FlowSessionBeanProvider provider; - public FlowSession(FlowWork flowWork, FlowNode flowNode, IFlowOperator createOperator, IFlowOperator currentOperator, IBindData bindData, Opinion opinion, List historyRecords) { + public FlowSession(FlowRecord flowRecord, + FlowWork flowWork, + FlowNode flowNode, + IFlowOperator createOperator, + IFlowOperator currentOperator, + IBindData bindData, + Opinion opinion, + List historyRecords) { + this.flowRecord = flowRecord; this.flowWork = flowWork; this.flowNode = flowNode; this.createOperator = createOperator; @@ -73,5 +95,124 @@ public OperatorResult createOperatorErrTrigger(long... operatorIds) { return new OperatorResult(operatorIds); } + /** + * 创建流程提醒 + * + * @param title 提醒标题 + * @return 提醒对象 + */ + public MessageResult createMessageResult(String title, String resultState) { + return MessageResult.create(title, resultState); + } + + + /** + * 创建流程提醒 + * + * @param title 提醒标题 + * @return 提醒对象 + */ + public MessageResult createMessageResult(String title) { + return MessageResult.create(title); + } + + /** + * 创建流程提醒 + * + * @param title 提醒标题 + * @param closeable 是否可关闭流程 + * @return 提醒对象 + */ + public MessageResult createMessageResult(String title, String resultState, boolean closeable) { + return MessageResult.create(title, resultState, closeable); + } + + + /** + * 创建流程提醒 + * + * @param title 提醒标题 + * @param items 提醒内容 + * @param closeable 是否可关闭流程 + * @return 提醒对象 + */ + public MessageResult createMessageResult(String title, String resultState, List items, boolean closeable) { + return MessageResult.create(title, resultState, items, closeable); + } + + /** + * 提交流程 + */ + public MessageResult submitFlow() { + if (flowRecord == null) { + throw new IllegalArgumentException("flow record is null"); + } + FlowService flowService = loadFlowService(); + FlowResult result = flowService.submitFlow(flowRecord.getId(), currentOperator, bindData, Opinion.pass(opinion.getAdvice())); + return MessageResult.create(result); + } + /** + * 驳回流程 + */ + public MessageResult rejectFlow() { + if (flowRecord == null) { + throw new IllegalArgumentException("flow record is null"); + } + FlowService flowService = loadFlowService(); + FlowResult result = flowService.submitFlow(flowRecord.getId(), currentOperator, bindData, Opinion.reject(opinion.getAdvice())); + return MessageResult.create(result); + } + + + /** + * 预提交流程 + */ + public MessageResult trySubmitFlow() { + if (flowRecord == null) { + throw new IllegalArgumentException("flow record is null"); + } + FlowService flowService = loadFlowService(); + FlowSubmitResult result = flowService.trySubmitFlow(flowRecord.getId(), currentOperator, bindData, Opinion.pass(opinion.getAdvice())); + return MessageResult.create(result); + } + + /** + * 保存流程 + */ + public void saveFlow() { + if (flowRecord == null) { + throw new IllegalArgumentException("flow record is null"); + } + FlowService flowService = loadFlowService(); + flowService.save(flowRecord.getId(), currentOperator, bindData, opinion.getAdvice()); + } + + + /** + * 催办流程 + */ + public void urgeFlow() { + if (flowRecord == null) { + throw new IllegalArgumentException("flow record is null"); + } + FlowService flowService = loadFlowService(); + flowService.urge(flowRecord.getId(), currentOperator); + } + + /** + * 撤回流程 + */ + public void recallFlow() { + if (flowRecord == null) { + throw new IllegalArgumentException("flow record is null"); + } + FlowService flowService = loadFlowService(); + flowService.recall(flowRecord.getId(), currentOperator); + } + + + private FlowService loadFlowService() { + return (FlowService) getBean("flowService"); + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowButton.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowButton.java new file mode 100644 index 00000000..6bd5c440 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowButton.java @@ -0,0 +1,78 @@ +package com.codingapi.springboot.flow.domain; + +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.em.FlowButtonType; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.result.MessageResult; +import com.codingapi.springboot.flow.script.GroovyShellContext; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * 流程按钮 + */ +@Setter +@Getter +public class FlowButton { + + /** + * 编号 + */ + private String id; + /** + * 名称 + */ + private String name; + /** + * 样式 + */ + private String style; + /** + * 事件类型 + */ + private FlowButtonType type; + /** + * 自定义事件内容 (后端脚本) + */ + private String groovy; + /** + * 排序 + */ + private int order; + + public boolean hasGroovy() { + return groovy != null; + } + + /** + * 执行按钮事件 + * @param flowRecord 流程记录 + * @param flowNode 节点 + * @param flowWork 流程设计器 + * @param createOperator 创建者 + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 意见 + * @param historyRecords 历史记录 + */ + public MessageResult run(FlowRecord flowRecord, + FlowNode flowNode, + FlowWork flowWork, + IFlowOperator createOperator, + IFlowOperator currentOperator, + IBindData bindData, + Opinion opinion, + List historyRecords) { + if (groovy != null) { + //执行脚本 + FlowSession session = new FlowSession(flowRecord, flowWork, flowNode, createOperator, currentOperator, bindData, opinion, historyRecords); + GroovyShellContext.ShellScript script = GroovyShellContext.getInstance().parse(groovy); + return (MessageResult) script.invokeMethod("run", session); + } + return null; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java index 2084a4f6..28342d75 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java @@ -2,7 +2,10 @@ import com.codingapi.springboot.flow.bind.BindDataSnapshot; import com.codingapi.springboot.flow.content.FlowSession; -import com.codingapi.springboot.flow.em.*; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.em.FlowStatus; +import com.codingapi.springboot.flow.em.FlowType; +import com.codingapi.springboot.flow.em.NodeType; import com.codingapi.springboot.flow.error.ErrTrigger; import com.codingapi.springboot.flow.error.ErrorResult; import com.codingapi.springboot.flow.generator.TitleGenerator; @@ -93,6 +96,11 @@ public class FlowNode { @Setter private ErrTrigger errTrigger; + /** + * 流程节点按钮 + */ + private List buttons; + public void verify(){ if (this.titleGenerator == null) { @@ -132,7 +140,8 @@ public FlowNodeSerializable toSerializable() { this.createTime, this.updateTime, this.timeout, - this.errTrigger == null ? null : this.errTrigger.getScript() + this.errTrigger == null ? null : this.errTrigger.getScript(), + this.buttons ); } @@ -147,7 +156,8 @@ public FlowNode(String id, OperatorMatcher operatorMatcher, long timeout, ErrTrigger errTrigger, - boolean editable) { + boolean editable, + List buttons) { this.id = id; this.code = code; this.name = name; @@ -161,6 +171,7 @@ public FlowNode(String id, this.errTrigger = errTrigger; this.timeout = timeout; this.editable = editable; + this.buttons = buttons; } @@ -303,4 +314,21 @@ public boolean isOverNode() { public boolean isStartNode() { return CODE_START.equals(this.code); } + + /** + * 是否传阅节点 + */ + public boolean isCirculate() { + return approvalType == ApprovalType.CIRCULATE; + } + + + public FlowButton getButton(String buttonId) { + for (FlowButton button : buttons) { + if (button.getId().equals(buttonId)) { + return button; + } + } + return null; + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java index 377aedd2..ffb91d08 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java @@ -227,6 +227,7 @@ public FlowWorkSerializable toSerializable() { updateTime, enable, postponedMax, + schema, nodes.stream().map(FlowNode::toSerializable).collect(Collectors.toCollection(ArrayList::new)), relations.stream().map(FlowRelation::toSerializable).collect(Collectors.toCollection(ArrayList::new))); } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java index 3f3321ae..2c1dc8f0 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java @@ -5,6 +5,9 @@ import lombok.Setter; import lombok.ToString; +import java.util.ArrayList; +import java.util.List; + /** * 审批意见 */ @@ -28,6 +31,8 @@ public class Opinion { public static final int RESULT_PASS = 2; // 审批结果 驳回 public static final int RESULT_REJECT = 3; + // 审批结果 抄送 + public static final int RESULT_CIRCULATE = 4; /** * 审批意见 @@ -42,12 +47,31 @@ public class Opinion { */ private int type; + /** + * 指定流程的操作者 + * operatorIds 为空时,表示不指定操作者,由流程配置的操作者匹配器决定 + */ + private List operatorIds; + public Opinion(String advice, int result, int type) { this.advice = advice; this.result = result; this.type = type; } + public Opinion specify(List operatorIds) { + this.operatorIds = operatorIds; + return this; + } + + public Opinion specify(long... operatorIds) { + List operatorIdList = new ArrayList<>(); + for (long operatorId : operatorIds) { + operatorIdList.add(operatorId); + } + return specify(operatorIdList); + } + public static Opinion save(String advice) { return new Opinion(advice, RESULT_SAVE, TYPE_DEFAULT); } @@ -68,6 +92,14 @@ public static Opinion unSignAutoSuccess() { return new Opinion("非会签自动审批", RESULT_PASS, TYPE_AUTO); } + public static Opinion circulate() { + return new Opinion("", RESULT_CIRCULATE, TYPE_AUTO); + } + + public boolean isCirculate() { + return result == RESULT_CIRCULATE; + } + public boolean isSuccess() { return result == RESULT_PASS; } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/ApprovalType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/ApprovalType.java index 60747587..ee58a275 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/ApprovalType.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/ApprovalType.java @@ -12,7 +12,11 @@ public enum ApprovalType { /** * 非会签 */ - UN_SIGN; + UN_SIGN, + /** + * 传阅 + */ + CIRCULATE; public static ApprovalType parser(String approvalType) { diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowButtonType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowButtonType.java new file mode 100644 index 00000000..0fc7c71e --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowButtonType.java @@ -0,0 +1,29 @@ +package com.codingapi.springboot.flow.em; + +public enum FlowButtonType { + + // 保存 + SAVE, + // 发起 + START, + // 提交 + SUBMIT, + // 预提交 + TRY_SUBMIT, + // 指定人员提交 + SPECIFY_SUBMIT, + // 驳回 + REJECT, + // 转办 + TRANSFER, + // 撤销 + RECALL, + // 延期 + POSTPONED, + // 催办 + URGE, + // 自定义 + CUSTOM, + // 前端 + VIEW, +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowSourceDirection.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowSourceDirection.java index deb82606..4963f388 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowSourceDirection.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowSourceDirection.java @@ -15,9 +15,13 @@ public enum FlowSourceDirection { */ REJECT, /** - * + * 转办 */ - TRANSFER; + TRANSFER, + /** + * 传阅 + */ + CIRCULATE; public static FlowSourceDirection parser(String type){ for(FlowSourceDirection flowSourceDirection :values()){ diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java index abee3ff0..79b54d00 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java @@ -13,6 +13,10 @@ public enum FlowType { * 已办 */ DONE, + /** + * 传阅 + */ + CIRCULATE, /** * 转办 */ diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/NodeType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/NodeType.java index ac87e905..0386f857 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/NodeType.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/NodeType.java @@ -13,6 +13,10 @@ public enum NodeType { * 审批 */ APPROVAL, + /** + * 传阅 + */ + CIRCULATE, /** * 结束 */ diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java index f005767e..ba6665ad 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java @@ -32,6 +32,8 @@ public class FlowApprovalEvent implements ISyncEvent { public static final int STATE_TODO = 7; // 催办 public static final int STATE_URGE = 8; + // 抄送 + public static final int STATE_CIRCULATE = 9; private final int state; diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java index ae252f0b..950f950e 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java @@ -88,7 +88,6 @@ public static OperatorMatcher specifyOperatorMatcher(long... userIds) { /** * 创建者操作者匹配器 * - * @param userIds 用户ids * @return 操作者匹配器 */ public static OperatorMatcher creatorOperatorMatcher() { diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java index f889f59f..a8f2be0f 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java @@ -45,12 +45,12 @@ public class FlowDetail { private final List operators; /** - * 创建者 + * 流程创建者 */ private final IFlowOperator flowCreator; /** - * 创建时间 + * 流程创建时间 */ private final long flowCreateTime; @@ -59,12 +59,18 @@ public class FlowDetail { */ private final List opinions; + /** + * 是否可以办理 + */ + private final boolean canHandle; + public FlowDetail(FlowRecord flowRecord, BindDataSnapshot snapshot, FlowWork flowWork, List historyRecords, - List operators) { + List operators, + boolean canHandle) { this.operators = operators; this.flowRecord = flowRecord; this.flowWork = flowWork; @@ -74,8 +80,24 @@ public FlowDetail(FlowRecord flowRecord, this.flowCreator = flowRecord.getCreateOperator(); this.flowCreateTime = flowRecord.getCreateTime(); this.flowNode = flowWork.getNodeByCode(flowRecord.getNodeCode()); + this.canHandle = canHandle; } + public FlowDetail(FlowWork flowWork, + FlowNode flowNode, + List operators, + boolean canHandle) { + this.flowWork = flowWork; + this.flowNode = flowNode; + this.operators = operators; + this.flowCreateTime = 0; + this.flowRecord = null; + this.historyRecords = null; + this.bindData = null; + this.opinions = null; + this.flowCreator = null; + this.canHandle = canHandle; + } @Getter public final class FlowOpinion { diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowSubmitResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowSubmitResult.java new file mode 100644 index 00000000..4bacea6e --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowSubmitResult.java @@ -0,0 +1,23 @@ +package com.codingapi.springboot.flow.pojo; + +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.Getter; + +import java.util.List; + +@Getter +public class FlowSubmitResult { + + private final FlowWork flowWork; + private final FlowNode flowNode; + private final List operators; + + public FlowSubmitResult(FlowWork flowWork, FlowNode flowNode, List operators) { + this.flowWork = flowWork; + this.flowNode = flowNode; + this.operators = operators; + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java index 79e372dc..75a7a5cd 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java @@ -12,6 +12,25 @@ public interface FlowRecordQuery { Page findAll(PageRequest pageRequest); + + /** + * 查看个人的未读与待办数据 + * + * @param operatorId 操作人 + * @return 流程记录 + */ + Page findUnReadByOperatorId(long operatorId, PageRequest pageRequest); + + + /** + * 查看个人的未读与待办数据(指定流程) + * + * @param operatorId 操作人 + * @param workCode 流程编码 + * @return 流程记录 + */ + Page findUnReadByOperatorId(long operatorId,String workCode, PageRequest pageRequest); + /** * 查看个人的待办数据 * diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java index fa96ce9b..81dbef11 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -230,6 +230,17 @@ public void submitRecord(IFlowOperator flowOperator, BindDataSnapshot snapshot, this.opinion = opinion; } + + /** + * 传阅流程 + */ + public void circulate() { + this.flowSourceDirection = FlowSourceDirection.CIRCULATE; + this.flowType = FlowType.CIRCULATE; + this.updateTime = System.currentTimeMillis(); + this.opinion = Opinion.circulate(); + } + /** * 转交流程 */ diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java index 568d35b5..892141ea 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java @@ -1,7 +1,7 @@ package com.codingapi.springboot.flow.repository; -import com.codingapi.springboot.flow.record.FlowProcess; import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.record.FlowProcess; /** * 流程仓库,每一个流程都会在创建时被创建一条process数据,用于标识流程 diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java index 623c420d..6948da3c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java @@ -6,7 +6,7 @@ /** - * 流转记录数据仓库 + * 流转记录数据仓库 */ public interface FlowRecordRepository { @@ -43,6 +43,7 @@ public interface FlowRecordRepository { /** * 根据流程id查询流程记录 + * * @param processId 流程id */ List findFlowRecordByProcessId(String processId); @@ -50,6 +51,7 @@ public interface FlowRecordRepository { /** * 查询所有未完成的流程记录 + * * @param processId 流程id * @return List of FlowRecord */ @@ -64,7 +66,9 @@ public interface FlowRecordRepository { /** * 删除流程记录 + * * @param childrenRecords 流程记录 */ void delete(List childrenRecords); + } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/result/MessageResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/result/MessageResult.java new file mode 100644 index 00000000..5bedea04 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/result/MessageResult.java @@ -0,0 +1,138 @@ +package com.codingapi.springboot.flow.result; + +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.pojo.FlowResult; +import com.codingapi.springboot.flow.pojo.FlowSubmitResult; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Setter +@Getter +public class MessageResult { + + /** + * 展示的标题 + */ + private String title; + + /** + * 展示状态 + */ + private ResultState resultState; + + /** + * 展示的内容 + */ + private List items; + + /** + * 是否可关闭流程 + */ + private boolean closeable; + + /** + * 添加一个展示项 + * + * @param label 标签 + * @param value 值 + * @return this + */ + public MessageResult addItem(String label, String value) { + if (items == null) { + items = new java.util.ArrayList<>(); + } + items.add(new Message(label, value)); + return this; + } + + /** + * 是否可关闭流程 + * + * @param closeable 是否可关闭 + * @return this + */ + public MessageResult closeable(boolean closeable) { + this.closeable = closeable; + return this; + } + + /** + * 展示状态 + * + * @param resultState 展示状态 + * @return this + */ + public MessageResult resultState(String resultState) { + this.resultState = ResultState.parser(resultState); + return this; + } + + + @Setter + @Getter + @AllArgsConstructor + public static class Message { + private String label; + private String value; + } + + + + public static MessageResult create(FlowSubmitResult result) { + List operators = result.getOperators(); + FlowNode flowNode = result.getFlowNode(); + MessageResult messageResult = new MessageResult(); + messageResult.setResultState(ResultState.SUCCESS); + messageResult.setTitle("下级节点提示"); + messageResult.addItem("下级审批节点", flowNode.getName()); + StringBuilder usernames = new StringBuilder(); + for (IFlowOperator operator : operators) { + usernames.append(operator.getName()).append(","); + } + messageResult.addItem("下级审批人", usernames.toString()); + return messageResult; + } + + public static MessageResult create(FlowResult result) { + List records = result.getRecords(); + FlowWork flowWork = result.getFlowWork(); + MessageResult messageResult = new MessageResult(); + messageResult.setResultState(ResultState.SUCCESS); + messageResult.setTitle("流程审批完成"); + for (FlowRecord record : records) { + FlowNode flowNode = flowWork.getNodeByCode(record.getNodeCode()); + messageResult.addItem("下级审批节点", flowNode.getName()); + messageResult.addItem("下级审批人", record.getCurrentOperator().getName()); + } + return messageResult; + } + + + public static MessageResult create(String title) { + return create(title, "SUCCESS", null, false); + } + + public static MessageResult create(String title, String resultState) { + return create(title, resultState, null, false); + } + + + public static MessageResult create(String title, String resultState, boolean closeable) { + return create(title, resultState, null, closeable); + } + + public static MessageResult create(String title, String resultState, List items, boolean closeable) { + MessageResult messageResult = new MessageResult(); + messageResult.setTitle(title); + messageResult.setItems(items); + messageResult.setResultState(ResultState.parser(resultState)); + messageResult.setCloseable(closeable); + return messageResult; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/result/ResultState.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/result/ResultState.java new file mode 100644 index 00000000..9048fd45 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/result/ResultState.java @@ -0,0 +1,23 @@ +package com.codingapi.springboot.flow.result; + +/** + * 状态数据 + */ +public enum ResultState { + SUCCESS, + INFO, + WARNING; + + + public static ResultState parser(String state) { + if ("SUCCESS".equalsIgnoreCase(state)) { + return SUCCESS; + } else if ("INFO".equalsIgnoreCase(state)) { + return INFO; + } else if ("WARNING".equalsIgnoreCase(state)) { + return WARNING; + } else { + return SUCCESS; + } + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java index 5e22c61e..d6e80dea 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java @@ -1,5 +1,6 @@ package com.codingapi.springboot.flow.serializable; +import com.codingapi.springboot.flow.domain.FlowButton; import com.codingapi.springboot.flow.domain.FlowNode; import com.codingapi.springboot.flow.em.ApprovalType; import com.codingapi.springboot.flow.em.NodeType; @@ -12,6 +13,7 @@ import lombok.Setter; import java.io.Serializable; +import java.util.List; /** * 流程节点序列化 @@ -86,9 +88,13 @@ public class FlowNodeSerializable implements Serializable { */ private String errTrigger; + /** + * 流程节点按钮 + */ + private List buttons; public FlowNode toFlowNode() { return new FlowNode(id, code, name, new TitleGenerator(titleGenerator), type, view, approvalType, - new OperatorMatcher(operatorMatcher), editable, createTime, updateTime, timeout, errTrigger == null ? null : new ErrTrigger(errTrigger)); + new OperatorMatcher(operatorMatcher), editable, createTime, updateTime, timeout, errTrigger == null ? null : new ErrTrigger(errTrigger),buttons); } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java index 050561a1..1903d63d 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java @@ -1,8 +1,10 @@ package com.codingapi.springboot.flow.serializable; +import com.codingapi.springboot.flow.domain.FlowButton; import com.codingapi.springboot.flow.domain.FlowNode; import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.em.FlowButtonType; import com.codingapi.springboot.flow.em.NodeType; import com.codingapi.springboot.flow.repository.FlowOperatorRepository; import com.esotericsoftware.kryo.Kryo; @@ -73,6 +75,11 @@ public class FlowWorkSerializable implements Serializable { @Setter private int postponedMax; + /** + * 流程的schema + */ + private String schema; + /** * 流程的节点(发起节点) */ @@ -97,6 +104,8 @@ public byte[] toSerializable() { kryo.register(FlowWorkSerializable.class); kryo.register(ApprovalType.class); kryo.register(NodeType.class); + kryo.register(FlowButton.class); + kryo.register(FlowButtonType.class); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Output output = new Output(outputStream); @@ -114,6 +123,8 @@ public static FlowWorkSerializable fromSerializable(byte[] bytes) { kryo.register(FlowWorkSerializable.class); kryo.register(ApprovalType.class); kryo.register(NodeType.class); + kryo.register(FlowButton.class); + kryo.register(FlowButtonType.class); return kryo.readObject(new Input(bytes), FlowWorkSerializable.class); } @@ -132,7 +143,7 @@ public FlowWork toFlowWork(FlowOperatorRepository flowOperatorRepository) { postponedMax, flowNodes, relations.stream().map((item) -> item.toFlowRelation(flowNodes)).collect(Collectors.toList()), - null + schema ); } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java index 2326a8fd..3b8f3aac 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java @@ -12,7 +12,7 @@ /** * 流程方向服务 */ -class FlowDirectionService { +public class FlowDirectionService { private final FlowWork flowWork; private final FlowNode flowNode; @@ -112,7 +112,7 @@ public boolean isDefaultBackRecord() { /** * 判断当前流程是否为通过流程 */ - public boolean isPassBackRecord() { + public boolean isPassRecord() { return flowSourceDirection == FlowSourceDirection.PASS; } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordBuilderService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java similarity index 53% rename from springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordBuilderService.java rename to springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java index 9d4f812a..b7210a8d 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordBuilderService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java @@ -9,20 +9,26 @@ import com.codingapi.springboot.flow.error.ErrorResult; import com.codingapi.springboot.flow.error.NodeResult; import com.codingapi.springboot.flow.error.OperatorResult; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.FlowOperatorRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import lombok.Getter; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** - * 流程记录构建服务 + * 流程节点服务 */ -class FlowRecordBuilderService { +public class FlowNodeService { + @Getter + private FlowNode nextNode; + private IFlowOperator nextOperator; private final FlowOperatorRepository flowOperatorRepository; private final FlowRecordRepository flowRecordRepository; @@ -31,6 +37,7 @@ class FlowRecordBuilderService { private final long preId; private final FlowWork flowWork; + private final FlowRecord flowRecord; private final Opinion opinion; private final IFlowOperator currentOperator; private final BindDataSnapshot snapshot; @@ -38,34 +45,99 @@ class FlowRecordBuilderService { private final IFlowOperator createOperator; - public FlowRecordBuilderService(FlowOperatorRepository flowOperatorRepository, - FlowRecordRepository flowRecordRepository, - BindDataSnapshot snapshot, - Opinion opinion, - IFlowOperator createOperator, - IFlowOperator currentOperator, - List historyRecords, - FlowWork flowWork, - String processId, - long preId) { + public FlowNodeService(FlowOperatorRepository flowOperatorRepository, + FlowRecordRepository flowRecordRepository, + BindDataSnapshot snapshot, + Opinion opinion, + IFlowOperator createOperator, + IFlowOperator currentOperator, + List historyRecords, + FlowWork flowWork, + FlowRecord flowRecord, + String processId, + long preId) { - if(createOperator==null){ - throw new IllegalArgumentException("createOperator is null"); - } - - this.createOperator = createOperator; this.flowOperatorRepository = flowOperatorRepository; - this.flowRecordRepository = flowRecordRepository; this.snapshot = snapshot; this.opinion = opinion; + this.createOperator = createOperator; this.currentOperator = currentOperator; + this.historyRecords = historyRecords; this.flowWork = flowWork; - - + this.flowRecord = flowRecord; this.processId = processId; this.preId = preId; - this.historyRecords = historyRecords; + } + + + /** + * 设置下一个节点 + */ + public void setNextNode(FlowNode nextNode) { + this.nextNode = nextNode; + this.nextOperator = currentOperator; + } + + + /** + * 加载下一个节点 + */ + public void loadNextPassNode(FlowNode currentNode) { + this.nextNode = matcherNextNode(currentNode, false); + this.nextOperator = currentOperator; + } + + /** + * 跳过传阅节点流转 + */ + public void skipCirculate() { + this.nextNode = matcherNextNode(nextNode, false); + this.nextOperator = currentOperator; + } + + /** + * 加载默认回退节点 + */ + public void loadDefaultBackNode(long parentRecordId) { + IFlowOperator flowOperator; + // 拒绝时,默认返回上一个已办节点 + FlowRecord preRecord = flowRecordRepository.getFlowRecordById(parentRecordId); + // 只寻找已办节点 + while (!preRecord.isDone()) { + // 继续寻找上一个节点 + preRecord = flowRecordRepository.getFlowRecordById(preRecord.getPreId()); + } + // 获取上一个节点的审批者,继续将审批者设置为当前审批者 + flowOperator = preRecord.getCurrentOperator(); + FlowNode nextNode = flowWork.getNodeByCode(preRecord.getNodeCode()); + if (nextNode == null) { + throw new IllegalArgumentException("next node not found"); + } + this.nextNode = nextNode; + this.nextOperator = flowOperator; + } + + + /** + * 加载自定义回退节点 + */ + public void loadCustomBackNode(FlowNode flowNode, long parentRecordId) { + FlowNode nextNode = this.matcherNextNode(flowNode, true); + if (nextNode == null) { + throw new IllegalArgumentException("next node not found"); + } + IFlowOperator flowOperator = currentOperator; + if (nextNode.isAnyOperatorMatcher()) { + // 如果是任意人员操作时则需要指定为当时审批人员为当前审批人员 + FlowRecord preFlowRecord = flowRecordRepository.getFlowRecordById(parentRecordId); + while (preFlowRecord.isTransfer() || !preFlowRecord.getNodeCode().equals(nextNode.getCode())) { + preFlowRecord = flowRecordRepository.getFlowRecordById(preFlowRecord.getPreId()); + } + flowOperator = preFlowRecord.getCurrentOperator(); + } + this.nextNode = nextNode; + this.nextOperator = flowOperator; } @@ -83,7 +155,7 @@ private FlowNode matcherNextNode(FlowNode flowNode, boolean back) { if (relations.isEmpty()) { throw new IllegalArgumentException("relation not found"); } - FlowSession flowSession = new FlowSession(flowWork, flowNode, createOperator, currentOperator, snapshot.toBindData(), opinion, historyRecords); + FlowSession flowSession = new FlowSession(flowRecord, flowWork, flowNode, createOperator, currentOperator, snapshot.toBindData(), opinion, historyRecords); List flowNodes = new ArrayList<>(); for (FlowRelation flowRelation : relations) { FlowNode node = flowRelation.trigger(flowSession); @@ -97,6 +169,101 @@ private FlowNode matcherNextNode(FlowNode flowNode, boolean back) { return flowNodes.get(0); } + + /** + * 创建流程记录 + * + * @return 流程记录 + */ + public List createRecord() { + // 创建下一节点的流程记录 + List records = this.createNextRecord(); + + // 检测流程是否为抄送节点 + while (this.nextNodeIsCirculate()) { + for (FlowRecord record : records) { + record.circulate(); + } + flowRecordRepository.save(records); + + for (FlowRecord record : records) { + IFlowOperator pushOperator = record.getCurrentOperator(); + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_CIRCULATE, + record, + pushOperator, + flowWork, + snapshot.toBindData()), + true); + } + + this.skipCirculate(); + + records = this.createNextRecord(); + } + return records; + } + + + /** + * 加载下一节点的操作者 + * + * @return 操作者 + */ + public List loadNextNodeOperators() { + FlowSession flowSession = new FlowSession(flowRecord, flowWork, nextNode, createOperator, nextOperator, snapshot.toBindData(), opinion, historyRecords); + List operators = nextNode.loadFlowNodeOperator(flowSession, flowOperatorRepository); + if (operators.isEmpty()) { + if (nextNode.hasErrTrigger()) { + ErrorResult errorResult = nextNode.errMatcher(flowSession); + if (errorResult == null) { + throw new IllegalArgumentException("errMatcher match error."); + } + if (errorResult.isOperator()) { + List operatorIds = ((OperatorResult) errorResult).getOperatorIds(); + operators = flowOperatorRepository.findByIds(operatorIds); + } + } + } + return operators; + } + + + private List createNextRecord() { + FlowSession flowSession = new FlowSession(flowRecord, flowWork, + nextNode, + createOperator, + nextOperator, + snapshot.toBindData(), + opinion, + historyRecords); + + long workId = flowWork.getId(); + List operators = nextNode.loadFlowNodeOperator(flowSession, flowOperatorRepository); + List customOperatorIds = opinion.getOperatorIds(); + if (customOperatorIds != null && !customOperatorIds.isEmpty()) { + operators = operators.stream().filter(operator -> customOperatorIds.contains(operator.getUserId())).collect(Collectors.toList()); + if (operators.size() != customOperatorIds.size()) { + throw new IllegalArgumentException("operator not match."); + } + } + List recordList; + if (operators.isEmpty()) { + recordList = this.errMatcher(nextNode, nextOperator); + if (recordList.isEmpty()) { + throw new IllegalArgumentException("operator not match."); + } + } else { + String recordTitle = nextNode.generateTitle(flowSession); + recordList = new ArrayList<>(); + for (IFlowOperator operator : operators) { + FlowRecord record = nextNode.createRecord(workId, flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot); + recordList.add(record); + } + } + return recordList; + } + /** * 异常匹配 * @@ -106,7 +273,7 @@ private FlowNode matcherNextNode(FlowNode flowNode, boolean back) { */ private List errMatcher(FlowNode currentNode, IFlowOperator currentOperator) { if (currentNode.hasErrTrigger()) { - FlowSession flowSession = new FlowSession(flowWork, currentNode, createOperator, currentOperator, snapshot.toBindData(), opinion, historyRecords); + FlowSession flowSession = new FlowSession(flowRecord, flowWork, currentNode, createOperator, currentOperator, snapshot.toBindData(), opinion, historyRecords); ErrorResult errorResult = currentNode.errMatcher(flowSession); if (errorResult == null) { throw new IllegalArgumentException("errMatcher match error."); @@ -118,9 +285,9 @@ private List errMatcher(FlowNode currentNode, IFlowOperator currentO List operatorIds = ((OperatorResult) errorResult).getOperatorIds(); List operators = flowOperatorRepository.findByIds(operatorIds); for (IFlowOperator operator : operators) { - FlowSession content = new FlowSession(flowWork, currentNode, createOperator, operator, snapshot.toBindData(), opinion, historyRecords); + FlowSession content = new FlowSession(flowRecord, flowWork, currentNode, createOperator, operator, snapshot.toBindData(), opinion, historyRecords); String recordTitle = currentNode.generateTitle(content); - FlowRecord record = currentNode.createRecord(flowWork.getId(),flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot); + FlowRecord record = currentNode.createRecord(flowWork.getId(), flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot); recordList.add(record); } return recordList; @@ -133,12 +300,12 @@ private List errMatcher(FlowNode currentNode, IFlowOperator currentO throw new IllegalArgumentException("node not found."); } List recordList = new ArrayList<>(); - FlowSession content = new FlowSession(flowWork, node, createOperator, currentOperator, snapshot.toBindData(), opinion, historyRecords); + FlowSession content = new FlowSession(flowRecord, flowWork, node, createOperator, currentOperator, snapshot.toBindData(), opinion, historyRecords); List matcherOperators = node.loadFlowNodeOperator(content, flowOperatorRepository); if (!matcherOperators.isEmpty()) { for (IFlowOperator matcherOperator : matcherOperators) { String recordTitle = node.generateTitle(content); - FlowRecord record = node.createRecord(flowWork.getId(),flowWork.getCode(), processId, preId, recordTitle, createOperator, matcherOperator, snapshot); + FlowRecord record = node.createRecord(flowWork.getId(), flowWork.getCode(), processId, preId, recordTitle, createOperator, matcherOperator, snapshot); recordList.add(record); } } @@ -151,101 +318,17 @@ private List errMatcher(FlowNode currentNode, IFlowOperator currentO /** - * 创建流程记录 - * - * @param currentNode 当前节点 - * @return 流程记录 - */ - public List createRecord(FlowNode currentNode, IFlowOperator currentOperator) { - return this.createRecord(currentNode,currentOperator,null); - } - - /** - * 创建流程记录 - * - * @param currentNode 当前节点 - * @param currentOperator 当前审批人 - * @param opinion 审批意见 - * @return 流程记录 - */ - public List createRecord(FlowNode currentNode, IFlowOperator currentOperator,Opinion opinion) { - FlowSession flowSession = new FlowSession(flowWork, currentNode, createOperator, currentOperator, snapshot.toBindData(), opinion, historyRecords); - long workId = flowWork.getId(); - List operators = currentNode.loadFlowNodeOperator(flowSession, flowOperatorRepository); - List recordList; - if (operators.isEmpty()) { - recordList= this.errMatcher(currentNode, currentOperator); - if (recordList.isEmpty()) { - throw new IllegalArgumentException("operator not match."); - } - } else { - String recordTitle = currentNode.generateTitle(flowSession); - recordList = new ArrayList<>(); - for (IFlowOperator operator : operators) { - FlowRecord record = currentNode.createRecord(workId,flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot); - recordList.add(record); - } - } - if(!recordList.isEmpty()){ - for (FlowRecord record:recordList){ - if(opinion!=null){ - record.updateOpinion(opinion); - } - } - } - - return recordList; - } - - - /** - * 创建下一个节点 + * 下一节点的类型 */ - public List createNextRecord(FlowNode flowNode) { - FlowNode nextNode = this.matcherNextNode(flowNode, false); - return this.createRecord(nextNode, currentOperator); + public boolean nextNodeIsCirculate() { + return nextNode.isCirculate(); } - /** - * 创建自定义的下级别节点 - */ - public List createCustomBackRecord(FlowNode flowNode, long parentRecordId) { - FlowNode nextNode = this.matcherNextNode(flowNode, true); - if (nextNode == null) { - throw new IllegalArgumentException("next node not found"); - } - IFlowOperator flowOperator = currentOperator; - if (nextNode.isAnyOperatorMatcher()) { - // 如果是任意人员操作时则需要指定为当时审批人员为当前审批人员 - FlowRecord preFlowRecord = flowRecordRepository.getFlowRecordById(parentRecordId); - while (preFlowRecord.isTransfer() || !preFlowRecord.getNodeCode().equals(nextNode.getCode())) { - preFlowRecord = flowRecordRepository.getFlowRecordById(preFlowRecord.getPreId()); - } - flowOperator = preFlowRecord.getCurrentOperator(); - } - return this.createRecord(nextNode, flowOperator); - } /** - * 创建默认拒绝时的流程记录 + * 下一节点是否结束节点 */ - public List createDefaultBackRecord(long parentRecordId) { - IFlowOperator flowOperator; - // 拒绝时,默认返回上一个节点 - FlowRecord preRecord = flowRecordRepository.getFlowRecordById(parentRecordId); - // 去除所有的转办的记录 - while (preRecord.isTransfer()) { - // 继续寻找上一个节点 - preRecord = flowRecordRepository.getFlowRecordById(preRecord.getPreId()); - } - // 获取上一个节点的审批者,继续将审批者设置为当前审批者 - flowOperator = preRecord.getCurrentOperator(); - FlowNode nextNode = flowWork.getNodeByCode(preRecord.getNodeCode()); - if (nextNode == null) { - throw new IllegalArgumentException("next node not found"); - } - return this.createRecord(nextNode, flowOperator); + public boolean nextNodeIsOver() { + return nextNode.isOverNode(); } - - } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java similarity index 91% rename from springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordService.java rename to springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java index 910529bb..b923f10b 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java @@ -13,7 +13,7 @@ /** * 流程记录服务(流程内部服务) */ -class FlowRecordService { +public class FlowRecordVerifyService { // constructor params private final long recordId; @@ -32,10 +32,10 @@ class FlowRecordService { @Getter private FlowRecord flowRecord; - public FlowRecordService(FlowRecordRepository flowRecordRepository, - FlowProcessRepository flowProcessRepository, - long recordId, - IFlowOperator currentOperator) { + public FlowRecordVerifyService(FlowRecordRepository flowRecordRepository, + FlowProcessRepository flowProcessRepository, + long recordId, + IFlowOperator currentOperator) { this.flowRecordRepository = flowRecordRepository; this.flowProcessRepository = flowProcessRepository; @@ -87,7 +87,9 @@ public void verifyFlowRecordIsDone() { */ public void verifyFlowRecordNotTodo() { if (flowRecord.isTodo()) { - throw new IllegalArgumentException("flow record is todo"); + if(!flowRecord.isStartRecord()) { + throw new IllegalArgumentException("flow record is todo"); + } } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index 6bb0d65d..2de3d976 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -1,45 +1,89 @@ package com.codingapi.springboot.flow.service; -import com.codingapi.springboot.flow.bind.BindDataSnapshot; import com.codingapi.springboot.flow.bind.IBindData; -import com.codingapi.springboot.flow.content.FlowSession; -import com.codingapi.springboot.flow.domain.FlowNode; -import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.domain.Opinion; -import com.codingapi.springboot.flow.em.FlowSourceDirection; -import com.codingapi.springboot.flow.event.FlowApprovalEvent; import com.codingapi.springboot.flow.pojo.FlowDetail; import com.codingapi.springboot.flow.pojo.FlowResult; -import com.codingapi.springboot.flow.record.FlowBackup; -import com.codingapi.springboot.flow.record.FlowProcess; -import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.pojo.FlowSubmitResult; import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.result.MessageResult; +import com.codingapi.springboot.flow.service.impl.*; import com.codingapi.springboot.flow.user.IFlowOperator; -import com.codingapi.springboot.framework.event.EventPusher; -import lombok.AllArgsConstructor; import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; +import org.springframework.util.StringUtils; /** * 流程服务 */ @Transactional -@AllArgsConstructor public class FlowService { + private final FlowDetailService flowDetailService; + private final FlowStartService flowStartService; + private final FlowSubmitService flowSubmitService; + private final FlowCustomEventService flowCustomEventService; + private final FlowRecallService flowRecallService; + private final FlowTrySubmitService flowTrySubmitService; + private final FlowSaveService flowSaveService; + private final FlowTransferService flowTransferService; + private final FlowPostponedService flowPostponedService; + private final FlowUrgeService flowUrgeService; + + + public FlowService(FlowWorkRepository flowWorkRepository, + FlowRecordRepository flowRecordRepository, + FlowBindDataRepository flowBindDataRepository, + FlowOperatorRepository flowOperatorRepository, + FlowProcessRepository flowProcessRepository, + FlowBackupRepository flowBackupRepository) { + this.flowDetailService = new FlowDetailService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository); + this.flowStartService = new FlowStartService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository, flowBackupRepository); + this.flowSubmitService = new FlowSubmitService(flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository); + this.flowCustomEventService = new FlowCustomEventService(flowRecordRepository, flowProcessRepository); + this.flowRecallService = new FlowRecallService(flowRecordRepository, flowProcessRepository); + this.flowTrySubmitService = new FlowTrySubmitService(flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository, flowWorkRepository, flowBackupRepository); + this.flowSaveService = new FlowSaveService(flowRecordRepository, flowBindDataRepository, flowProcessRepository); + this.flowTransferService = new FlowTransferService(flowRecordRepository, flowBindDataRepository, flowProcessRepository); + this.flowPostponedService = new FlowPostponedService(flowRecordRepository, flowProcessRepository); + this.flowUrgeService = new FlowUrgeService(flowRecordRepository, flowProcessRepository); + } + + /** + * 流程详情 + * + * @param recordId 流程记录id + * @param workCode 流程编码 + * @return 流程详情 + */ + public FlowDetail detail(long recordId, String workCode, IFlowOperator currentOperator) { + if (StringUtils.hasText(workCode)) { + return flowDetailService.detail(workCode, currentOperator); + } else { + return flowDetailService.detail(recordId, currentOperator); + } + } + + /** + * 流程详情 + * + * @param recordId 流程记录id + * @return 流程详情 + */ + public FlowDetail detail(long recordId, IFlowOperator currentOperator) { + return this.detail(recordId, null, currentOperator); + } + - private final FlowWorkRepository flowWorkRepository; - private final FlowRecordRepository flowRecordRepository; - private final FlowBindDataRepository flowBindDataRepository; - private final FlowOperatorRepository flowOperatorRepository; - private final FlowProcessRepository flowProcessRepository; - private final FlowBackupRepository flowBackupRepository; + /** + * 流程详情 + * + * @param workCode 流程编号 + * @return 流程详情 + */ + public FlowDetail detail(String workCode, IFlowOperator currentOperator) { + return this.detail(0, workCode, currentOperator); + } /** @@ -49,7 +93,7 @@ public class FlowService { * @return 流程详情 */ public FlowDetail detail(long recordId) { - return detail(recordId, null); + return this.detail(recordId, null, null); } /** @@ -60,22 +104,7 @@ public FlowDetail detail(long recordId) { * @param time 延期时间 */ public void postponed(long recordId, IFlowOperator currentOperator, long time) { - FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, - flowProcessRepository, - recordId, currentOperator); - - flowRecordService.loadFlowRecord(); - flowRecordService.verifyFlowRecordSubmitState(); - flowRecordService.verifyFlowRecordCurrentOperator(); - flowRecordService.loadFlowWork(); - flowRecordService.verifyFlowRecordNotFinish(); - flowRecordService.verifyFlowRecordNotDone(); - - FlowRecord flowRecord = flowRecordService.getFlowRecord(); - FlowWork flowWork = flowRecordService.getFlowWork(); - - flowRecord.postponedTime(flowWork.getPostponedMax(), time); - flowRecordRepository.update(flowRecord); + flowPostponedService.postponed(recordId, currentOperator, time); } /** @@ -85,63 +114,7 @@ public void postponed(long recordId, IFlowOperator currentOperator, long time) { * @param currentOperator 当前操作者 */ public void urge(long recordId, IFlowOperator currentOperator) { - FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, - flowProcessRepository, - recordId, currentOperator); - flowRecordService.loadFlowRecord(); - flowRecordService.loadFlowWork(); - flowRecordService.verifyFlowRecordIsDone(); - - FlowRecord flowRecord = flowRecordService.getFlowRecord(); - FlowWork flowWork = flowRecordService.getFlowWork(); - - List todoRecords = flowRecordRepository.findTodoFlowRecordByProcessId(flowRecord.getProcessId()); - - // 推送催办消息 - for (FlowRecord record : todoRecords) { - IFlowOperator pushOperator = record.getCurrentOperator(); - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_URGE, record, pushOperator, flowWork, null),true); - } - - } - - /** - * 流程详情 - * 如果传递了currentOperator为流程的审批者时,在查看详情的时候可以将流程记录标记为已读 - * - * @param recordId 流程记录id - * @param currentOperator 当前操作者 - */ - public FlowDetail detail(long recordId, IFlowOperator currentOperator) { - - FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, - flowProcessRepository, - recordId, currentOperator); - - flowRecordService.loadFlowRecord(); - flowRecordService.setFlowRecordRead(); - flowRecordService.loadFlowWork(); - - FlowRecord flowRecord = flowRecordService.getFlowRecord(); - FlowWork flowWork = flowRecordService.getFlowWork(); - - - BindDataSnapshot snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); - List flowRecords = - flowRecordRepository.findFlowRecordByProcessId(flowRecord.getProcessId()). - stream(). - sorted((o1, o2) -> (int) (o2.getId() - o1.getId())) - .collect(Collectors.toList()); - - List operators = new ArrayList<>(); - // 获取所有的操作者 - for (FlowRecord record : flowRecords) { - operators.add(record.getCreateOperator()); - operators.add(record.getCurrentOperator()); - operators.add(record.getInterferedOperator()); - } - - return new FlowDetail(flowRecord, snapshot, flowWork, flowRecords, operators); + flowUrgeService.urge(recordId, currentOperator); } @@ -171,62 +144,7 @@ public FlowResult interfere(long recordId, IFlowOperator currentOperator, IBindD * @param advice 转办意见 */ public void transfer(long recordId, IFlowOperator currentOperator, IFlowOperator targetOperator, IBindData bindData, String advice) { - - FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, - flowProcessRepository, - recordId, currentOperator); - - flowRecordService.loadFlowRecord(); - flowRecordService.verifyFlowRecordSubmitState(); - flowRecordService.verifyFlowRecordCurrentOperator(); - flowRecordService.verifyTargetOperatorIsNotCurrentOperator(targetOperator); - - flowRecordService.loadFlowWork(); - flowRecordService.loadFlowNode(); - - flowRecordService.verifyFlowRecordIsTodo(); - - FlowRecord flowRecord = flowRecordService.getFlowRecord(); - FlowWork flowWork = flowRecordService.getFlowWork(); - FlowNode flowNode = flowRecordService.getFlowNode(); - - - // 保存绑定数据 - BindDataSnapshot snapshot = new BindDataSnapshot(bindData); - flowBindDataRepository.save(snapshot); - - // 构建审批意见 - Opinion opinion = Opinion.transfer(advice); - - // 设置自己的流程状态为转办已完成 - flowRecord.transfer(currentOperator, snapshot, opinion); - flowRecordRepository.update(flowRecord); - - // 获取创建者 - IFlowOperator createOperator = flowRecord.getCreateOperator(); - - // 与当前流程同级的流程记录 - List historyRecords; - if (flowRecord.isStartRecord()) { - historyRecords = new ArrayList<>(); - } else { - historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()); - } - - // 创建新的待办标题 - FlowSession content = new FlowSession(flowWork, flowNode, createOperator, targetOperator, snapshot.toBindData(), opinion, historyRecords); - String generateTitle = flowNode.generateTitle(content); - - // 创建转办记录 - FlowRecord transferRecord = flowRecord.copy(); - transferRecord.transferToTodo(generateTitle, targetOperator); - flowRecordRepository.save(Collections.singletonList(transferRecord)); - - // 推送转办消息 - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TRANSFER, flowRecord, currentOperator, flowWork, snapshot.toBindData()),true); - - // 推送待办消息 - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, transferRecord, targetOperator, flowWork, snapshot.toBindData()),true); + flowTransferService.transfer(recordId, currentOperator, targetOperator, bindData, advice); } @@ -239,24 +157,7 @@ public void transfer(long recordId, IFlowOperator currentOperator, IFlowOperator * @param advice 审批意见 */ public void save(long recordId, IFlowOperator currentOperator, IBindData bindData, String advice) { - FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, - flowProcessRepository, - recordId, currentOperator); - flowRecordService.loadFlowRecord(); - flowRecordService.verifyFlowRecordSubmitState(); - flowRecordService.verifyFlowRecordCurrentOperator(); - flowRecordService.loadFlowWork(); - flowRecordService.loadFlowNode(); - flowRecordService.verifyFlowNodeEditableState(false); - - Opinion opinion = Opinion.save(advice); - FlowRecord flowRecord = flowRecordService.getFlowRecord(); - BindDataSnapshot snapshot = new BindDataSnapshot(flowRecord.getSnapshotId(), bindData); - flowBindDataRepository.update(snapshot); - - flowRecord.setOpinion(opinion); - flowRecordService.flowRecordRepository.update(flowRecord); - + flowSaveService.save(recordId, currentOperator, bindData, advice); } @@ -269,74 +170,36 @@ public void save(long recordId, IFlowOperator currentOperator, IBindData bindDat * @param advice 审批意见 */ public FlowResult startFlow(String workCode, IFlowOperator operator, IBindData bindData, String advice) { - // 检测流程是否存在 - FlowWork flowWork = flowWorkRepository.getFlowWorkByCode(workCode); - if (flowWork == null) { - throw new IllegalArgumentException("flow work not found"); - } - flowWork.verify(); - flowWork.enableValidate(); - - // 流程数据备份 - FlowBackup flowBackup = flowBackupRepository.getFlowBackupByWorkIdAndVersion(flowWork.getId(), flowWork.getUpdateTime()); - if (flowBackup == null) { - flowBackup = flowBackupRepository.backup(flowWork); - } - - // 保存流程 - FlowProcess flowProcess = new FlowProcess(flowBackup.getId(), operator); - flowProcessRepository.save(flowProcess); - - // 保存绑定数据 - BindDataSnapshot snapshot = new BindDataSnapshot(bindData); - flowBindDataRepository.save(snapshot); + return flowStartService.startFlow(workCode, operator, bindData, advice); + } - // 创建流程id - String processId = flowProcess.getProcessId(); - // 构建审批意见 - Opinion opinion = Opinion.pass(advice); + /** + * 尝试提交流程 (流程过程中) + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public FlowSubmitResult trySubmitFlow(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + return flowTrySubmitService.trySubmitFlow(recordId, currentOperator, bindData, opinion); + } - // 获取开始节点 - FlowNode start = flowWork.getStartNode(); - if (start == null) { - throw new IllegalArgumentException("start node not found"); - } - // 设置开始流程的上一个流程id - long preId = 0; - - List historyRecords = new ArrayList<>(); - - FlowRecordBuilderService flowRecordBuilderService = new FlowRecordBuilderService( - flowOperatorRepository, - flowRecordRepository, - snapshot, - opinion, - operator, - operator, - historyRecords, - flowWork, - processId, - preId - ); - - // 创建待办记录 - List records = flowRecordBuilderService.createRecord(start, operator, opinion); - if (records.isEmpty()) { - throw new IllegalArgumentException("flow record not found"); - } - // 保存流程记录 - flowRecordRepository.save(records); - // 推送事件消息 - for (FlowRecord record : records) { - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_CREATE, record, operator, flowWork, snapshot.toBindData()),true); - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, record, operator, flowWork, snapshot.toBindData()),true); - } - // 当前的审批记录 - return new FlowResult(flowWork, records); + /** + * 尝试提交流程 (发起流程) + * + * @param workCode 流程编码 + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public FlowSubmitResult trySubmitFlow(String workCode, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + return flowTrySubmitService.trySubmitFlow(workCode, currentOperator, bindData, opinion); } + /** * 提交流程 * @@ -346,137 +209,21 @@ public FlowResult startFlow(String workCode, IFlowOperator operator, IBindData b * @param opinion 审批意见 */ public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + return flowSubmitService.submitFlow(recordId, currentOperator, bindData, opinion); + } - FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, flowProcessRepository, recordId, currentOperator); - - // 加载流程 - flowRecordService.loadFlowRecord(); - // 验证流程的提交状态 - flowRecordService.verifyFlowRecordSubmitState(); - // 验证当前操作者 - flowRecordService.verifyFlowRecordCurrentOperator(); - // 加载流程设计 - flowRecordService.loadFlowWork(); - // 加载流程节点 - flowRecordService.loadFlowNode(); - // 验证没有子流程 - flowRecordService.verifyChildrenRecordsIsEmpty(); - - // 获取流程记录对象 - FlowRecord flowRecord = flowRecordService.getFlowRecord(); - FlowNode flowNode = flowRecordService.getFlowNode(); - FlowWork flowWork = flowRecordService.getFlowWork(); - - - // 保存流程表单快照数据 - BindDataSnapshot snapshot = null; - if (flowNode.isEditable()) { - snapshot = new BindDataSnapshot(bindData); - flowBindDataRepository.save(snapshot); - } else { - snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); - } - - // 审批方向判断服务 - FlowDirectionService flowDirectionService = new FlowDirectionService(flowRecordService.getFlowNode(), flowRecordService.getFlowWork(), opinion); - - // 加载流程审批方向 - flowDirectionService.loadFlowSourceDirection(); - // 验证审批方向 - flowDirectionService.verifyFlowSourceDirection(); - - // 根据当前方向提交流程 - FlowSourceDirection flowSourceDirection = flowDirectionService.getFlowSourceDirection(); - flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); - flowRecordRepository.update(flowRecord); - - // 与当前流程同级的流程记录 - List historyRecords; - if (flowRecord.isStartRecord()) { - historyRecords = new ArrayList<>(); - } else { - historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()); - } - flowDirectionService.bindHistoryRecords(historyRecords); - - // 判断流程是否结束(会签时需要所有人都通过) - if (flowNode.isSign()) { - boolean next = flowDirectionService.hasCurrentFlowNodeIsDone(); - if (next) { - List todoRecords = historyRecords.stream().filter(FlowRecord::isTodo).collect(Collectors.toList()); - return new FlowResult(flowWork, todoRecords); - } - } - - // 非会签下,当有人提交以后,将所有未提交的流程都自动提交,然后再执行下一节点 - if (flowNode.isUnSign()) { - for (FlowRecord record : historyRecords) { - if (record.isTodo() && record.getId() != flowRecord.getId()) { - record.autoPass(currentOperator, snapshot); - flowRecordRepository.update(flowRecord); - } - } - } - - // 根据所有提交意见,重新加载审批方向 - flowSourceDirection = flowDirectionService.reloadFlowSourceDirection(); - - - // 判断流程是否完成 - if (flowDirectionService.hasCurrentFlowIsFinish()) { - flowRecord.finish(); - flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); - flowRecordRepository.update(flowRecord); - flowRecordRepository.finishFlowRecordByProcessId(flowRecord.getProcessId()); - - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_FINISH, flowRecord, currentOperator, flowWork, snapshot.toBindData()),true); - return new FlowResult(flowWork, flowRecord); - } - - // 获取流程的发起者 - IFlowOperator createOperator = flowRecord.getCreateOperator(); - - // 构建流程创建器 - FlowRecordBuilderService flowRecordBuilderService = new FlowRecordBuilderService( - flowOperatorRepository, - flowRecordRepository, - snapshot, - opinion, - createOperator, - currentOperator, - historyRecords, - flowWork, - flowRecord.getProcessId(), - flowRecord.getId() - ); - - // 创建下一节点的流程记录 - List records; - // 审批通过并进入下一节点 - if (flowDirectionService.isPassBackRecord()) { - records = flowRecordBuilderService.createNextRecord(flowNode); - // 审批拒绝返回上一节点 - } else if (flowDirectionService.isDefaultBackRecord()) { - records = flowRecordBuilderService.createDefaultBackRecord(flowRecord.getPreId()); - } else { - // 审批拒绝,并且自定了返回节点 - records = flowRecordBuilderService.createCustomBackRecord(flowNode, flowRecord.getPreId()); - } - - // 保存流程记录 - flowRecordRepository.save(records); - - // 推送审批事件消息 - int eventState = flowSourceDirection == FlowSourceDirection.PASS ? FlowApprovalEvent.STATE_PASS : FlowApprovalEvent.STATE_REJECT; - EventPusher.push(new FlowApprovalEvent(eventState, flowRecord, currentOperator, flowWork, snapshot.toBindData()),true); - - // 推送待办事件消息 - for (FlowRecord record : records) { - IFlowOperator pushOperator = record.getCurrentOperator(); - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, record, pushOperator, flowWork, snapshot.toBindData()),true); - } - return new FlowResult(flowWork, records); + /** + * 自定义事件 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param buttonId 按钮id + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public MessageResult customFlowEvent(long recordId, IFlowOperator currentOperator, String buttonId, IBindData bindData, Opinion opinion) { + return flowCustomEventService.customFlowEvent(recordId, currentOperator, buttonId, bindData, opinion); } @@ -487,37 +234,8 @@ public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBind * @param currentOperator 当前操作者 */ public void recall(long recordId, IFlowOperator currentOperator) { - FlowRecordService flowRecordService = new FlowRecordService(flowRecordRepository, - flowProcessRepository, - recordId, currentOperator); - - flowRecordService.loadFlowRecord(); - flowRecordService.verifyFlowRecordCurrentOperator(); - flowRecordService.loadFlowWork(); - flowRecordService.loadFlowNode(); - flowRecordService.verifyFlowRecordNotFinish(); - flowRecordService.verifyFlowRecordNotTodo(); - - FlowRecord flowRecord = flowRecordService.getFlowRecord(); - FlowWork flowWork = flowRecordService.getFlowWork(); - - // 下一流程的流程记录 - List childrenRecords = flowRecordRepository.findFlowRecordByPreId(recordId); - // 下一流程均为办理且未读 - - if (childrenRecords.isEmpty()) { - throw new IllegalArgumentException("flow record not submit"); - } - - boolean allUnDone = childrenRecords.stream().allMatch(item -> item.isUnRead() && item.isTodo()); - if (!allUnDone) { - throw new IllegalArgumentException("flow record not recall"); - } - flowRecord.recall(); - flowRecordRepository.update(flowRecord); - - flowRecordRepository.delete(childrenRecords); - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_RECALL, flowRecord, currentOperator, flowWork, null),true); + flowRecallService.recall(recordId, currentOperator); } + } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowCustomEventService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowCustomEventService.java new file mode 100644 index 00000000..b7ab1dfc --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowCustomEventService.java @@ -0,0 +1,76 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.FlowButton; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.result.MessageResult; +import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Transactional +@AllArgsConstructor +public class FlowCustomEventService { + + private final FlowRecordRepository flowRecordRepository; + private final FlowProcessRepository flowProcessRepository; + + /** + * 自定义事件 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param buttonId 按钮id + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public MessageResult customFlowEvent(long recordId, IFlowOperator currentOperator, String buttonId, IBindData bindData, Opinion opinion) { + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, flowProcessRepository, recordId, currentOperator); + + // 加载流程 + flowRecordVerifyService.loadFlowRecord(); + // 验证流程的提交状态 + flowRecordVerifyService.verifyFlowRecordSubmitState(); + // 验证当前操作者 + flowRecordVerifyService.verifyFlowRecordCurrentOperator(); + // 加载流程设计 + flowRecordVerifyService.loadFlowWork(); + // 加载流程节点 + flowRecordVerifyService.loadFlowNode(); + // 验证没有子流程 + flowRecordVerifyService.verifyChildrenRecordsIsEmpty(); + + // 获取流程记录对象 + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); + FlowNode flowNode = flowRecordVerifyService.getFlowNode(); + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + + // 与当前流程同级的流程记录 + List historyRecords; + if (flowRecord.isStartRecord()) { + historyRecords = new ArrayList<>(); + } else { + historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()); + } + + // 获取流程的发起者 + IFlowOperator createOperator = flowRecord.getCreateOperator(); + FlowButton flowButton = flowNode.getButton(buttonId); + if (flowButton == null) { + throw new IllegalArgumentException("flow button not found"); + } + if (!flowButton.hasGroovy()) { + throw new IllegalArgumentException("flow button not groovy"); + } + return flowButton.run(flowRecord, flowNode, flowWork, createOperator, currentOperator, bindData, opinion, historyRecords); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java new file mode 100644 index 00000000..b2ea7409 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java @@ -0,0 +1,114 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Transactional +@AllArgsConstructor +public class FlowDetailService { + + private final FlowWorkRepository flowWorkRepository; + private final FlowRecordRepository flowRecordRepository; + private final FlowBindDataRepository flowBindDataRepository; + private final FlowOperatorRepository flowOperatorRepository; + private final FlowProcessRepository flowProcessRepository; + + + /** + * 流程详情 + * 如果传递了currentOperator为流程的审批者时,在查看详情的时候可以将流程记录标记为已读 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public FlowDetail detail(long recordId, IFlowOperator currentOperator) { + + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + flowRecordVerifyService.loadFlowRecord(); + flowRecordVerifyService.setFlowRecordRead(); + flowRecordVerifyService.loadFlowWork(); + + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + + + BindDataSnapshot snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + List flowRecords = + flowRecordRepository.findFlowRecordByProcessId(flowRecord.getProcessId()). + stream(). + sorted((o1, o2) -> (int) (o2.getId() - o1.getId())) + .collect(Collectors.toList()); + + List operators = new ArrayList<>(); + // 获取所有的操作者 + for (FlowRecord record : flowRecords) { + operators.add(record.getCreateOperator()); + operators.add(record.getCurrentOperator()); + if (record.getInterferedOperator() != null) { + operators.add(record.getInterferedOperator()); + } + } + + return new FlowDetail(flowRecord, snapshot, flowWork, flowRecords, operators, currentOperator != null && flowRecord.isTodo() && flowRecord.isOperator(currentOperator)); + } + + + /** + * 发起流程详情 + * 如果传递了currentOperator为流程的审批者时,在查看详情的时候可以将流程记录标记为已读 + * + * @param workCode 流程记录id + * @param currentOperator 当前操作者 + */ + public FlowDetail detail(String workCode, IFlowOperator currentOperator) { + + if (currentOperator == null) { + throw new IllegalArgumentException("current operator is null"); + } + + FlowWork flowWork = flowWorkRepository.getFlowWorkByCode(workCode); + if (flowWork == null) { + throw new IllegalArgumentException("flow work not found"); + } + flowWork.enableValidate(); + + // 获取开始节点 + FlowNode flowNode = flowWork.getStartNode(); + + FlowSession flowSession = new FlowSession( + null, + flowWork, + flowNode, + currentOperator, + currentOperator, + null, + null, + new ArrayList<>()); + + List operators = flowNode.loadFlowNodeOperator(flowSession, flowOperatorRepository); + + List operatorIds = operators.stream().map(IFlowOperator::getUserId).collect(Collectors.toList()); + if (!operatorIds.contains(currentOperator.getUserId())) { + throw new IllegalArgumentException("current operator is not flow operator"); + } + + return new FlowDetail(flowWork, flowNode, operators,true); + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowPostponedService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowPostponedService.java new file mode 100644 index 00000000..6b11b0e5 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowPostponedService.java @@ -0,0 +1,44 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +@AllArgsConstructor +public class FlowPostponedService { + + private final FlowRecordRepository flowRecordRepository; + private final FlowProcessRepository flowProcessRepository; + + /** + * 延期待办 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param time 延期时间 + */ + public void postponed(long recordId, IFlowOperator currentOperator, long time) { + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + flowRecordVerifyService.loadFlowRecord(); + flowRecordVerifyService.verifyFlowRecordSubmitState(); + flowRecordVerifyService.verifyFlowRecordCurrentOperator(); + flowRecordVerifyService.loadFlowWork(); + flowRecordVerifyService.verifyFlowRecordNotFinish(); + flowRecordVerifyService.verifyFlowRecordNotDone(); + + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + + flowRecord.postponedTime(flowWork.getPostponedMax(), time); + flowRecordRepository.update(flowRecord); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java new file mode 100644 index 00000000..e0d98d0a --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java @@ -0,0 +1,73 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collections; +import java.util.List; + +@Transactional +@AllArgsConstructor +public class FlowRecallService { + + private final FlowRecordRepository flowRecordRepository; + private final FlowProcessRepository flowProcessRepository; + + /** + * 撤回流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public void recall(long recordId, IFlowOperator currentOperator) { + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + flowRecordVerifyService.loadFlowRecord(); + flowRecordVerifyService.verifyFlowRecordCurrentOperator(); + flowRecordVerifyService.loadFlowWork(); + flowRecordVerifyService.loadFlowNode(); + flowRecordVerifyService.verifyFlowRecordNotFinish(); + flowRecordVerifyService.verifyFlowRecordNotTodo(); + + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + + // 下一流程的流程记录 + List childrenRecords = flowRecordRepository.findFlowRecordByPreId(recordId); + // 下一流程均为办理且未读 + + // 如果是在开始节点撤销,则直接删除 + if (flowRecord.isStartRecord() && flowRecord.isTodo()) { + if (!childrenRecords.isEmpty()) { + throw new IllegalArgumentException("flow record not recall"); + } + flowRecordRepository.delete(Collections.singletonList(flowRecord)); + } else { + // 如果是在中间节点撤销,则需要判断是否所有的子流程都是未读状态 + if (childrenRecords.isEmpty()) { + throw new IllegalArgumentException("flow record not submit"); + } + + boolean allUnDone = childrenRecords.stream().allMatch(item -> item.isUnRead() && item.isTodo()); + if (!allUnDone) { + throw new IllegalArgumentException("flow record not recall"); + } + flowRecord.recall(); + flowRecordRepository.update(flowRecord); + + flowRecordRepository.delete(childrenRecords); + } + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_RECALL, flowRecord, currentOperator, flowWork, null), true); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java new file mode 100644 index 00000000..174c18a3 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java @@ -0,0 +1,51 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowBindDataRepository; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +@AllArgsConstructor +public class FlowSaveService { + + private final FlowRecordRepository flowRecordRepository; + private final FlowBindDataRepository flowBindDataRepository; + private final FlowProcessRepository flowProcessRepository; + + /** + * 保存流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param advice 审批意见 + */ + public void save(long recordId, IFlowOperator currentOperator, IBindData bindData, String advice) { + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + flowRecordVerifyService.loadFlowRecord(); + flowRecordVerifyService.verifyFlowRecordSubmitState(); + flowRecordVerifyService.verifyFlowRecordCurrentOperator(); + flowRecordVerifyService.loadFlowWork(); + flowRecordVerifyService.loadFlowNode(); + flowRecordVerifyService.verifyFlowNodeEditableState(false); + + Opinion opinion = Opinion.save(advice); + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); + BindDataSnapshot snapshot = new BindDataSnapshot(flowRecord.getSnapshotId(), bindData); + flowBindDataRepository.update(snapshot); + + flowRecord.setOpinion(opinion); + flowRecordRepository.update(flowRecord); + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java new file mode 100644 index 00000000..80047a84 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java @@ -0,0 +1,142 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.FlowSourceDirection; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.pojo.FlowResult; +import com.codingapi.springboot.flow.record.FlowBackup; +import com.codingapi.springboot.flow.record.FlowProcess; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowNodeService; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Transactional +@AllArgsConstructor +public class FlowStartService { + + private final FlowWorkRepository flowWorkRepository; + private final FlowRecordRepository flowRecordRepository; + private final FlowBindDataRepository flowBindDataRepository; + private final FlowOperatorRepository flowOperatorRepository; + private final FlowProcessRepository flowProcessRepository; + private final FlowBackupRepository flowBackupRepository; + + + /** + * 发起流程 (不自动提交到下一节点) + * + * @param workCode 流程编码 + * @param operator 操作者 + * @param bindData 绑定数据 + * @param advice 审批意见 + */ + public FlowResult startFlow(String workCode, IFlowOperator operator, IBindData bindData, String advice) { + // 检测流程是否存在 + FlowWork flowWork = flowWorkRepository.getFlowWorkByCode(workCode); + if (flowWork == null) { + throw new IllegalArgumentException("flow work not found"); + } + flowWork.verify(); + flowWork.enableValidate(); + + // 流程数据备份 + FlowBackup flowBackup = flowBackupRepository.getFlowBackupByWorkIdAndVersion(flowWork.getId(), flowWork.getUpdateTime()); + if (flowBackup == null) { + flowBackup = flowBackupRepository.backup(flowWork); + } + + // 保存流程 + FlowProcess flowProcess = new FlowProcess(flowBackup.getId(), operator); + flowProcessRepository.save(flowProcess); + + // 保存绑定数据 + BindDataSnapshot snapshot = new BindDataSnapshot(bindData); + flowBindDataRepository.save(snapshot); + + // 创建流程id + String processId = flowProcess.getProcessId(); + + // 构建审批意见 + Opinion opinion = Opinion.pass(advice); + + // 获取开始节点 + FlowNode start = flowWork.getStartNode(); + if (start == null) { + throw new IllegalArgumentException("start node not found"); + } + // 设置开始流程的上一个流程id + long preId = 0; + + List historyRecords = new ArrayList<>(); + + FlowNodeService flowNodeService = new FlowNodeService(flowOperatorRepository, + flowRecordRepository, + snapshot, + opinion, + operator, + operator, + historyRecords, + flowWork, + null, + processId, + preId); + + flowNodeService.setNextNode(start); + + // 创建待办记录 + List records = flowNodeService.createRecord(); + if (records.isEmpty()) { + throw new IllegalArgumentException("flow record not found"); + } else { + for (FlowRecord record : records) { + record.updateOpinion(opinion); + } + } + + // 检测流程是否结束 + if (flowNodeService.nextNodeIsOver()) { + for (FlowRecord record : records) { + record.submitRecord(operator, snapshot, opinion, FlowSourceDirection.PASS); + record.finish(); + } + + flowRecordRepository.save(records); + + // 推送事件 + for (FlowRecord record : records) { + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_CREATE, record, operator, flowWork, snapshot.toBindData()), true); + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_FINISH, + record, + operator, + flowWork, + snapshot.toBindData()), + true); + } + return new FlowResult(flowWork, records); + } + + // 保存流程记录 + flowRecordRepository.save(records); + + // 推送事件消息 + for (FlowRecord record : records) { + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_CREATE, record, operator, flowWork, snapshot.toBindData()), true); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, record, operator, flowWork, snapshot.toBindData()), true); + } + // 当前的审批记录 + return new FlowResult(flowWork, records); + } + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java new file mode 100644 index 00000000..77d379c6 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -0,0 +1,196 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.FlowSourceDirection; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.pojo.FlowResult; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowBindDataRepository; +import com.codingapi.springboot.flow.repository.FlowOperatorRepository; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.service.FlowDirectionService; +import com.codingapi.springboot.flow.service.FlowNodeService; +import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Transactional +@AllArgsConstructor +public class FlowSubmitService { + + private final FlowRecordRepository flowRecordRepository; + private final FlowBindDataRepository flowBindDataRepository; + private final FlowOperatorRepository flowOperatorRepository; + private final FlowProcessRepository flowProcessRepository; + + /** + * 提交流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, flowProcessRepository, recordId, currentOperator); + + // 加载流程 + flowRecordVerifyService.loadFlowRecord(); + // 验证流程的提交状态 + flowRecordVerifyService.verifyFlowRecordSubmitState(); + // 验证当前操作者 + flowRecordVerifyService.verifyFlowRecordCurrentOperator(); + // 加载流程设计 + flowRecordVerifyService.loadFlowWork(); + // 加载流程节点 + flowRecordVerifyService.loadFlowNode(); + // 验证没有子流程 + flowRecordVerifyService.verifyChildrenRecordsIsEmpty(); + + // 获取流程记录对象 + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); + FlowNode flowNode = flowRecordVerifyService.getFlowNode(); + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + + + // 保存流程表单快照数据 + BindDataSnapshot snapshot = null; + if (flowNode.isEditable()) { + snapshot = new BindDataSnapshot(bindData); + flowBindDataRepository.save(snapshot); + } else { + snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + } + + // 审批方向判断服务 + FlowDirectionService flowDirectionService = new FlowDirectionService(flowRecordVerifyService.getFlowNode(), flowRecordVerifyService.getFlowWork(), opinion); + + // 加载流程审批方向 + flowDirectionService.loadFlowSourceDirection(); + // 验证审批方向 + flowDirectionService.verifyFlowSourceDirection(); + + // 根据当前方向提交流程 + FlowSourceDirection flowSourceDirection = flowDirectionService.getFlowSourceDirection(); + flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); + flowRecordRepository.update(flowRecord); + + // 与当前流程同级的流程记录 + List historyRecords; + if (flowRecord.isStartRecord()) { + historyRecords = new ArrayList<>(); + } else { + historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()); + } + flowDirectionService.bindHistoryRecords(historyRecords); + + // 判断流程是否结束(会签时需要所有人都通过) + if (flowNode.isSign()) { + boolean next = flowDirectionService.hasCurrentFlowNodeIsDone(); + if (next) { + List todoRecords = historyRecords.stream().filter(FlowRecord::isTodo).collect(Collectors.toList()); + return new FlowResult(flowWork, todoRecords); + } + } + + // 非会签下,当有人提交以后,将所有未提交的流程都自动提交,然后再执行下一节点 + if (flowNode.isUnSign()) { + for (FlowRecord record : historyRecords) { + if (record.isTodo() && record.getId() != flowRecord.getId()) { + record.autoPass(currentOperator, snapshot); + flowRecordRepository.update(flowRecord); + } + } + } + + // 根据所有提交意见,重新加载审批方向 + flowSourceDirection = flowDirectionService.reloadFlowSourceDirection(); + + // 获取流程的发起者 + IFlowOperator createOperator = flowRecord.getCreateOperator(); + + // 构建流程创建器 + FlowNodeService flowNodeService = new FlowNodeService( + flowOperatorRepository, + flowRecordRepository, + snapshot, + opinion, + createOperator, + currentOperator, + historyRecords, + flowWork, + flowRecord, + flowRecord.getProcessId(), + flowRecord.getId() + ); + + // 审批通过并进入下一节点 + if (flowDirectionService.isPassRecord()) { + flowNodeService.loadNextPassNode(flowNode); + // 审批拒绝返回上一节点 + } else if (flowDirectionService.isDefaultBackRecord()) { + flowNodeService.loadDefaultBackNode(flowRecord.getPreId()); + } else { + // 审批拒绝,并且自定了返回节点 + flowNodeService.loadCustomBackNode(flowNode, flowRecord.getPreId()); + } + + List records = flowNodeService.createRecord(); + + // 判断流程是否完成 + if (flowNodeService.nextNodeIsOver()) { + flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); + flowRecord.finish(); + flowRecordRepository.update(flowRecord); + flowRecordRepository.finishFlowRecordByProcessId(flowRecord.getProcessId()); + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_FINISH, + flowRecord, + currentOperator, + flowWork, + snapshot.toBindData()), + true); + if(!records.isEmpty()) { + return new FlowResult(flowWork, records.get(0)); + } + return new FlowResult(flowWork, flowRecord); + } + + // 保存流程记录 + flowRecordRepository.save(records); + + // 推送审批事件消息 + int eventState = flowSourceDirection == FlowSourceDirection.PASS ? FlowApprovalEvent.STATE_PASS : FlowApprovalEvent.STATE_REJECT; + EventPusher.push(new FlowApprovalEvent(eventState, + flowRecord, + currentOperator, + flowWork, + snapshot.toBindData()), + true); + + // 推送待办事件消息 + for (FlowRecord record : records) { + IFlowOperator pushOperator = record.getCurrentOperator(); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, + record, + pushOperator, + flowWork, + snapshot.toBindData()), + true); + } + + return new FlowResult(flowWork, records); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTransferService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTransferService.java new file mode 100644 index 00000000..429d79f7 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTransferService.java @@ -0,0 +1,100 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.content.FlowSession; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowBindDataRepository; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Transactional +@AllArgsConstructor +public class FlowTransferService { + + private final FlowRecordRepository flowRecordRepository; + private final FlowBindDataRepository flowBindDataRepository; + private final FlowProcessRepository flowProcessRepository; + + + /** + * 转办流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param targetOperator 转办操作者 + * @param bindData 绑定数据 + * @param advice 转办意见 + */ + public void transfer(long recordId, IFlowOperator currentOperator, IFlowOperator targetOperator, IBindData bindData, String advice) { + + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + flowRecordVerifyService.loadFlowRecord(); + flowRecordVerifyService.verifyFlowRecordSubmitState(); + flowRecordVerifyService.verifyFlowRecordCurrentOperator(); + flowRecordVerifyService.verifyTargetOperatorIsNotCurrentOperator(targetOperator); + + flowRecordVerifyService.loadFlowWork(); + flowRecordVerifyService.loadFlowNode(); + + flowRecordVerifyService.verifyFlowRecordIsTodo(); + + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + FlowNode flowNode = flowRecordVerifyService.getFlowNode(); + + + // 保存绑定数据 + BindDataSnapshot snapshot = new BindDataSnapshot(bindData); + flowBindDataRepository.save(snapshot); + + // 构建审批意见 + Opinion opinion = Opinion.transfer(advice); + + // 设置自己的流程状态为转办已完成 + flowRecord.transfer(currentOperator, snapshot, opinion); + flowRecordRepository.update(flowRecord); + + // 获取创建者 + IFlowOperator createOperator = flowRecord.getCreateOperator(); + + // 与当前流程同级的流程记录 + List historyRecords; + if (flowRecord.isStartRecord()) { + historyRecords = new ArrayList<>(); + } else { + historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()); + } + + // 创建新的待办标题 + FlowSession content = new FlowSession(flowRecord, flowWork, flowNode, createOperator, targetOperator, snapshot.toBindData(), opinion, historyRecords); + String generateTitle = flowNode.generateTitle(content); + + // 创建转办记录 + FlowRecord transferRecord = flowRecord.copy(); + transferRecord.transferToTodo(generateTitle, targetOperator); + flowRecordRepository.save(Collections.singletonList(transferRecord)); + + // 推送转办消息 + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TRANSFER, flowRecord, currentOperator, flowWork, snapshot.toBindData()), true); + + // 推送待办消息 + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, transferRecord, targetOperator, flowWork, snapshot.toBindData()), true); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java new file mode 100644 index 00000000..c48fab7f --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java @@ -0,0 +1,250 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.FlowSourceDirection; +import com.codingapi.springboot.flow.pojo.FlowSubmitResult; +import com.codingapi.springboot.flow.record.FlowBackup; +import com.codingapi.springboot.flow.record.FlowProcess; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowDirectionService; +import com.codingapi.springboot.flow.service.FlowNodeService; +import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Transactional +@AllArgsConstructor +public class FlowTrySubmitService { + + private final FlowRecordRepository flowRecordRepository; + private final FlowBindDataRepository flowBindDataRepository; + private final FlowOperatorRepository flowOperatorRepository; + private final FlowProcessRepository flowProcessRepository; + private final FlowWorkRepository flowWorkRepository; + private final FlowBackupRepository flowBackupRepository; + + + /** + * 尝试提交流程 (流程过程中) + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public FlowSubmitResult trySubmitFlow(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, flowProcessRepository, recordId, currentOperator); + + // 加载流程 + flowRecordVerifyService.loadFlowRecord(); + // 验证流程的提交状态 + flowRecordVerifyService.verifyFlowRecordSubmitState(); + // 验证当前操作者 + flowRecordVerifyService.verifyFlowRecordCurrentOperator(); + // 加载流程设计 + flowRecordVerifyService.loadFlowWork(); + // 加载流程节点 + flowRecordVerifyService.loadFlowNode(); + // 验证没有子流程 + flowRecordVerifyService.verifyChildrenRecordsIsEmpty(); + + // 获取流程记录对象 copy 流程数据防止影响原有数据 + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord().copy(); + FlowNode flowNode = flowRecordVerifyService.getFlowNode(); + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + + return trySubmitFlow(flowWork, flowNode, flowRecord, currentOperator, bindData, opinion); + } + + + /** + * 预提交流程数据查询 + * + * @param flowWork 流程设计 + * @param flowNode 流程节点 + * @param flowRecord 流程记录 + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 审批意见 + * @return FlowSubmitResult + */ + private FlowSubmitResult trySubmitFlow(FlowWork flowWork, FlowNode flowNode, FlowRecord flowRecord, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + + // 保存流程表单快照数据 + BindDataSnapshot snapshot = null; + if (flowNode.isEditable()) { + snapshot = new BindDataSnapshot(bindData); + } else { + snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + } + + // 审批方向判断服务 + FlowDirectionService flowDirectionService = new FlowDirectionService(flowNode, flowWork, opinion); + + // 加载流程审批方向 + flowDirectionService.loadFlowSourceDirection(); + // 验证审批方向 + flowDirectionService.verifyFlowSourceDirection(); + + // 根据当前方向提交流程 + FlowSourceDirection flowSourceDirection = flowDirectionService.getFlowSourceDirection(); + flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); + + // 与当前流程同级的流程记录 + List historyRecords; + if (flowRecord.isStartRecord()) { + historyRecords = new ArrayList<>(); + } else { + // copy 流程数据防止影响原有数据 + historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()).stream().map(FlowRecord::copy).collect(Collectors.toList()); + } + flowDirectionService.bindHistoryRecords(historyRecords); + + // 判断流程是否结束(会签时需要所有人都通过) + if (flowNode.isSign()) { + boolean next = flowDirectionService.hasCurrentFlowNodeIsDone(); + if (next) { + List todoRecords = historyRecords.stream().filter(FlowRecord::isTodo).collect(Collectors.toList()); + return new FlowSubmitResult(flowWork, flowNode, todoRecords.stream().map(FlowRecord::getCurrentOperator).collect(Collectors.toList())); + } + } + + // 非会签下,当有人提交以后,将所有未提交的流程都自动提交,然后再执行下一节点 + if (flowNode.isUnSign()) { + for (FlowRecord record : historyRecords) { + if (record.isTodo() && record.getId() != flowRecord.getId()) { + record.autoPass(currentOperator, snapshot); + } + } + } + + // 根据所有提交意见,重新加载审批方向 + flowDirectionService.reloadFlowSourceDirection(); + + // 获取流程的发起者 + IFlowOperator createOperator = flowRecord.getCreateOperator(); + + // 构建流程创建器 + FlowNodeService flowNodeService = new FlowNodeService( + flowOperatorRepository, + flowRecordRepository, + snapshot, + opinion, + createOperator, + currentOperator, + historyRecords, + flowWork, + flowRecord, + flowRecord.getProcessId(), + flowRecord.getId() + ); + + // 审批通过并进入下一节点 + if (flowDirectionService.isPassRecord()) { + flowNodeService.loadNextPassNode(flowNode); + // 审批拒绝返回上一节点 + } else if (flowDirectionService.isDefaultBackRecord()) { + flowNodeService.loadDefaultBackNode(flowRecord.getPreId()); + } else { + // 审批拒绝,并且自定了返回节点 + flowNodeService.loadCustomBackNode(flowNode, flowRecord.getPreId()); + } + + FlowNode nextNode = flowNodeService.getNextNode(); + + List operators = flowNodeService.loadNextNodeOperators(); + return new FlowSubmitResult(flowWork, nextNode, operators); + } + + + /** + * 尝试提交流程 (发起流程) + * + * @param workCode 流程编码 + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public FlowSubmitResult trySubmitFlow(String workCode, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + // 检测流程是否存在 + FlowWork flowWork = flowWorkRepository.getFlowWorkByCode(workCode); + if (flowWork == null) { + throw new IllegalArgumentException("flow work not found"); + } + flowWork.verify(); + flowWork.enableValidate(); + + // 流程数据备份 + FlowBackup flowBackup = flowBackupRepository.getFlowBackupByWorkIdAndVersion(flowWork.getId(), flowWork.getUpdateTime()); + if (flowBackup == null) { + flowBackup = flowBackupRepository.backup(flowWork); + } + + // 保存流程 + FlowProcess flowProcess = new FlowProcess(flowBackup.getId(), currentOperator); + + // 保存绑定数据 + BindDataSnapshot snapshot = new BindDataSnapshot(bindData); + + // 创建流程id + String processId = flowProcess.getProcessId(); + + // 获取开始节点 + FlowNode start = flowWork.getStartNode(); + if (start == null) { + throw new IllegalArgumentException("start node not found"); + } + // 设置开始流程的上一个流程id + long preId = 0; + + List historyRecords = new ArrayList<>(); + + FlowNodeService flowNodeService = new FlowNodeService(flowOperatorRepository, + flowRecordRepository, + snapshot, + opinion, + currentOperator, + currentOperator, + historyRecords, + flowWork, + null, + processId, + preId); + + flowNodeService.setNextNode(start); + + FlowRecord startRecord = null; + + // 创建待办记录 + List records = flowNodeService.createRecord(); + if (records.isEmpty()) { + throw new IllegalArgumentException("flow record not found"); + } else { + for (FlowRecord record : records) { + record.updateOpinion(opinion); + startRecord = record; + } + } + + // 检测流程是否结束 + if (flowNodeService.nextNodeIsOver()) { + for (FlowRecord record : records) { + record.submitRecord(currentOperator, snapshot, opinion, FlowSourceDirection.PASS); + record.finish(); + startRecord = record; + } + } + return this.trySubmitFlow(flowWork, start, startRecord, currentOperator, bindData, opinion); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowUrgeService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowUrgeService.java new file mode 100644 index 00000000..2ebfbfb8 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowUrgeService.java @@ -0,0 +1,50 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Transactional +@AllArgsConstructor +public class FlowUrgeService { + + + private final FlowRecordRepository flowRecordRepository; + private final FlowProcessRepository flowProcessRepository; + + /** + * 催办流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public void urge(long recordId, IFlowOperator currentOperator) { + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + flowRecordVerifyService.loadFlowRecord(); + flowRecordVerifyService.loadFlowWork(); + flowRecordVerifyService.verifyFlowRecordIsDone(); + + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + + List todoRecords = flowRecordRepository.findTodoFlowRecordByProcessId(flowRecord.getProcessId()); + + // 推送催办消息 + for (FlowRecord record : todoRecords) { + IFlowOperator pushOperator = record.getCurrentOperator(); + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_URGE, record, pushOperator, flowWork, null), true); + } + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java index 36cfde5c..02d88d4b 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java @@ -43,8 +43,6 @@ public List findFlowRecordByPreId(long preId) { return cache.stream().filter(record -> record.getPreId() == preId).collect(Collectors.toList()); } - - @Override public List findFlowRecordByProcessId(String processId) { return cache.stream().filter(record -> record.getProcessId().equals(processId)) @@ -61,13 +59,24 @@ public Page findAll(PageRequest pageRequest) { return new PageImpl<>(cache); } - @Override - public Page findDoneByOperatorId(long operatorId,PageRequest pageRequest) { + public Page findDoneByOperatorId(long operatorId, PageRequest pageRequest) { List flowRecords = cache.stream().filter(record -> record.isDone() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); return new PageImpl<>(flowRecords); } + @Override + public Page findUnReadByOperatorId(long operatorId, PageRequest pageRequest) { + List flowRecords = cache.stream().filter(record -> record.isUnRead() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + + @Override + public Page findUnReadByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { + List flowRecords = cache.stream().filter(record -> record.isUnRead() && record.getWorkCode().equals(workCode) && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + @Override public Page findDoneByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { List flowRecords = cache.stream().filter(record -> record.isDone() @@ -78,7 +87,7 @@ public Page findDoneByOperatorId(long operatorId, String workCode, P } @Override - public Page findInitiatedByOperatorId(long operatorId,PageRequest pageRequest) { + public Page findInitiatedByOperatorId(long operatorId, PageRequest pageRequest) { List flowRecords = cache.stream().filter(record -> record.isInitiated() && record.getCreateOperator().getUserId() == operatorId).collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @@ -96,7 +105,7 @@ record -> record.isInitiated() @Override - public Page findTodoByOperatorId(long operatorId,PageRequest pageRequest) { + public Page findTodoByOperatorId(long operatorId, PageRequest pageRequest) { List flowRecords = cache.stream().filter(record -> record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @@ -108,13 +117,12 @@ public Page findTodoByOperatorId(long operatorId, String workCode, P } @Override - public Page findTimeoutTodoByOperatorId(long operatorId,PageRequest pageRequest) { + public Page findTimeoutTodoByOperatorId(long operatorId, PageRequest pageRequest) { List flowRecords = cache.stream().filter(record -> record.isTimeout() && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); return new PageImpl<>(flowRecords); } - @Override public Page findTimeoutTodoByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { List flowRecords = cache.stream().filter( @@ -127,7 +135,7 @@ record -> record.isTimeout() @Override - public Page findPostponedTodoByOperatorId(long operatorId,PageRequest pageRequest) { + public Page findPostponedTodoByOperatorId(long operatorId, PageRequest pageRequest) { List flowRecords = cache.stream().filter(record -> record.isPostponed() && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); return new PageImpl<>(flowRecords); } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/BuildTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/BuildTest.java index 47c426a6..e9c739a9 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/BuildTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/BuildTest.java @@ -27,15 +27,18 @@ void build() { .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("抄送节点", "circulate", "default", ApprovalType.CIRCULATE, OperatorMatcher.anyOperatorMatcher()) .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") - .relation("结束节点", "manager", "over") + .relation("抄送节点", "manager", "circulate") + .relation("结束节点", "circulate", "over") .build(); assertEquals("请假流程", flowWork.getTitle()); - assertEquals(4, flowWork.getNodes().size()); - assertEquals(3, flowWork.getRelations().size()); + assertEquals(5, flowWork.getNodes().size()); + assertEquals(4, flowWork.getRelations().size()); byte[] bytes = flowWork.toSerializable().toSerializable(); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/CirculateTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/CirculateTest.java new file mode 100644 index 00000000..7e198d49 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/CirculateTest.java @@ -0,0 +1,138 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class CirculateTest { + + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository,userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository,flowProcessRepository,flowBackupRepository); + + + @Test + void circulate(){ + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("抄送节点1", "circulate1", "default", ApprovalType.CIRCULATE, OperatorMatcher.specifyOperatorMatcher(lorne.getUserId())) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("抄送节点2", "circulate2", "default", ApprovalType.CIRCULATE, OperatorMatcher.specifyOperatorMatcher(user.getUserId())) + .node("抄送节点3", "circulate3", "default", ApprovalType.CIRCULATE, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + + .relations() + .relation("部门领导审批", "start", "dept") + .relation("抄送节点1", "dept", "circulate1") + .relation("总经理审批", "circulate1", "manager") + .relation("抄送节点1", "manager", "circulate2") + .relation("抄送节点2", "circulate2", "circulate3") + .relation("结束节点", "circulate3", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findUnReadByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + // 保存流程 + leave.setTitle("我要出去看看~~"); + flowService.save(userTodo.getId(), user, leave,"暂存"); + + // 查看流程详情 + FlowDetail flowDetail = flowService.detail(userTodo.getId(), user); + assertEquals("我要出去看看~~", ((Leave) flowDetail.getBindData()).getTitle()); + assertTrue(flowDetail.getFlowRecord().isRead()); + + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(6, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(6, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + + + // 查看lorne的未读 + List lorneTodos = flowRecordRepository.findUnReadByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java index 219b8472..97010832 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java @@ -55,7 +55,7 @@ void errorMatcherOperatorTest(){ .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createOperatorErrTrigger("+dept.getId()+")}"), true) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -108,21 +108,18 @@ void errorMatcherOperatorTest(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); + assertEquals(4, snapshots.size()); } @@ -150,7 +147,7 @@ void errorMatcherNodeTest(){ .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createNodeErrTrigger('manager')}"), true) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -199,20 +196,17 @@ void errorMatcherNodeTest(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(3, records.size()); + assertEquals(2, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(3, records.size()); + assertEquals(2, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(4, snapshots.size()); + assertEquals(3, snapshots.size()); } } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java index 40bcb8b4..113facaa 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java @@ -8,14 +8,17 @@ import com.codingapi.springboot.flow.flow.Leave; import com.codingapi.springboot.flow.matcher.OperatorMatcher; import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.pojo.FlowSubmitResult; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.*; import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.IFlowOperator; import com.codingapi.springboot.flow.user.User; import org.junit.jupiter.api.Test; import org.springframework.data.domain.PageRequest; import java.util.List; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.*; @@ -55,7 +58,7 @@ void entrustTest() { .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -112,21 +115,18 @@ void entrustTest() { // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); + assertEquals(4, snapshots.size()); } @@ -183,18 +183,15 @@ void passAndRejectTest() { flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(3, records.size()); + assertEquals(2, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(4, snapshots.size()); + assertEquals(3, snapshots.size()); } @@ -220,7 +217,7 @@ void passTest() { .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -273,21 +270,19 @@ void passTest() { // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); + assertEquals(0, userTodos.size()); - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); + assertEquals(4, snapshots.size()); } @@ -314,7 +309,7 @@ void saveDisableTest() { .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId()), false) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -359,21 +354,18 @@ void saveDisableTest() { // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(4, snapshots.size()); + assertEquals(3, snapshots.size()); } @@ -448,21 +440,18 @@ void interfereTest() { // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); + assertEquals(4, snapshots.size()); } @@ -491,7 +480,7 @@ void transferTest() { .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -547,21 +536,18 @@ void transferTest() { // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(5, records.size()); + assertEquals(4, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(5, records.size()); + assertEquals(4, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(6, snapshots.size()); + assertEquals(5, snapshots.size()); } @@ -668,7 +654,7 @@ void rejectTest() { .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -727,7 +713,7 @@ void rejectTest() { flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(6, records.size()); + assertEquals(5, records.size()); } @@ -737,9 +723,12 @@ void rejectTest() { * 撤销流程测试 */ @Test - void recallTest() { + void recallTest1() { PageRequest pageRequest = PageRequest.of(0, 1000); + User lorne = new User("lorne"); + userRepository.save(lorne); + User user = new User("张飞"); userRepository.save(user); @@ -753,9 +742,9 @@ void recallTest() { .title("请假流程") .nodes() .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) - .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),lorne.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -778,14 +767,21 @@ void recallTest() { // 提交流程 FlowRecord userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + FlowSubmitResult flowSubmitResult = flowService.trySubmitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(flowSubmitResult.getOperators().size(), 2); + assertTrue(flowSubmitResult.getOperators().stream().map(IFlowOperator::getUserId).collect(Collectors.toList()).contains(dept.getUserId())); + assertTrue(flowSubmitResult.getOperators().stream().map(IFlowOperator::getUserId).collect(Collectors.toList()).contains(lorne.getUserId())); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(dept.getUserId())); + // 撤销流程 flowService.recall(userTodo.getId(), user); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); assertEquals(1, userTodos.size()); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(dept.getUserId())); // 查看部门经理的待办 List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); @@ -799,7 +795,7 @@ void recallTest() { assertEquals(1, userTodos.size()); userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(dept.getUserId())); deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); assertEquals(1, deptTodos.size()); @@ -814,7 +810,61 @@ void recallTest() { flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(6, records.size()); + assertEquals(5, records.size()); + + + } + + + /** + * 撤销流程测试 + */ + @Test + void recallTest2() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 撤销流程 + FlowRecord userTodo = userTodos.get(0); + flowService.recall(userTodo.getId(), user); + + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(0, records.size()); } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java index ecc58e5c..7321f63c 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java @@ -98,13 +98,10 @@ void flowTest() { flowService.submitFlow(deptTodo.getId(), lorne, leave, Opinion.pass("转交给领导审批通过")); bossTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); - assertEquals(1, bossTodos.size()); - - bossTodo = bossTodos.get(0); - flowService.submitFlow(bossTodo.getId(), lorne, leave, Opinion.pass("领导审批通过")); + assertEquals(0, bossTodos.size()); List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(6, records.size()); + assertEquals(5, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java index f9d09469..dea70b23 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java @@ -55,7 +55,7 @@ void relationTest1(){ .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "over",new OutTrigger("def run(content){content.getBindData().getDays()<=5}"),1,false) @@ -91,23 +91,20 @@ void relationTest1(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(3, records.size()); + assertEquals(2, records.size()); // 最终用户确认 userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); + assertEquals(0, userTodos.size()); - // 提交流程 - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(3, records.size()); + assertEquals(2, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(4, snapshots.size()); + assertEquals(3, snapshots.size()); } @@ -138,7 +135,7 @@ void relationTest2(){ .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "over",new OutTrigger("def run(content){content.getBindData().getDays()<=5}"),1,false) @@ -183,24 +180,21 @@ void relationTest2(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 最终用户确认 userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); + assertEquals(0, userTodos.size()); - // 提交流程 - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); + assertEquals(4, snapshots.size()); } @@ -229,7 +223,7 @@ void relationTest3(){ .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "over",new OutTrigger("def run(content){content.getBindData().getDays()<=5}"),1,false) @@ -299,16 +293,12 @@ void relationTest3(){ // 用户修改确认 userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - // 提交流程 - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(7, snapshots.size()); + assertEquals(6, snapshots.size()); } } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/QueryTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/QueryTest.java index d975ec01..b4da2889 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/QueryTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/QueryTest.java @@ -54,7 +54,7 @@ void queryUserToDo(){ .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -97,21 +97,18 @@ void queryUserToDo(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); + assertEquals(4, snapshots.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); assertEquals(0, userTodos.size()); @@ -148,7 +145,7 @@ void queryUserTimeoutTodo(){ .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher(),100,true) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -202,21 +199,18 @@ void queryUserTimeoutTodo(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent();; - assertEquals(4, records.size()); + assertEquals(3, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); + assertEquals(4, snapshots.size()); userTodos = flowRecordRepository.findTimeoutTodoByOperatorId(user.getUserId(), pageRequest).getContent(); assertEquals(0, userTodos.size()); @@ -254,7 +248,7 @@ void queryUserPostponedTodo(){ .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher(),100,true) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -314,21 +308,19 @@ void queryUserPostponedTodo(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); + assertEquals(0, userTodos.size()); - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); + assertEquals(4, snapshots.size()); userTodos = flowRecordRepository.findPostponedTodoByOperatorId(user.getUserId(), pageRequest).getContent(); assertEquals(0, userTodos.size()); @@ -366,7 +358,7 @@ void queryUserDone(){ .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -409,29 +401,26 @@ void queryUserDone(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); FlowDetail flowDetail = flowService.detail(records.get(0).getId(), user); - assertEquals(4, flowDetail.getHistoryRecords().size()); - assertEquals(4, flowDetail.getOpinions().size()); + assertEquals(3, flowDetail.getHistoryRecords().size()); + assertEquals(3, flowDetail.getOpinions().size()); List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); + assertEquals(4, snapshots.size()); List userDones = flowRecordRepository.findDoneByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(2, userDones.size()); + assertEquals(1, userDones.size()); List deptDones = flowRecordRepository.findDoneByOperatorId(dept.getUserId(), pageRequest).getContent(); assertEquals(1, deptDones.size()); @@ -439,6 +428,7 @@ void queryUserDone(){ List bossDones = flowRecordRepository.findDoneByOperatorId(boss.getUserId(), pageRequest).getContent(); assertEquals(1, bossDones.size()); + assertTrue(bossDones.stream().allMatch(FlowRecord::isRead)); } @@ -466,7 +456,7 @@ void queryUserInitiated(){ .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -509,21 +499,18 @@ void queryUserInitiated(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); + assertEquals(4, snapshots.size()); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java index ce99c991..e41a359a 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java @@ -6,7 +6,8 @@ import com.codingapi.springboot.flow.user.User; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; public class ScriptBuildTest { @@ -14,14 +15,14 @@ public class ScriptBuildTest { @Test void copy() { User user = new User("张三"); - String script = "{\"nodes\":[{\"id\":\"e7699cab-e20b-4606-af66-fb8d782fd0f8\",\"type\":\"start-node\",\"x\":1005,\"y\":153,\"properties\":{\"name\":\"开始节点\",\"code\":\"start\",\"type\":\"START\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCreateOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCreateOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"e7699cab-e20b-4606-af66-fb8d782fd0f8\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"creator\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"0d6638e9-0f98-45de-a5ad-8d55702158f7\",\"type\":\"node-node\",\"x\":722,\"y\":392,\"properties\":{\"name\":\"部门审批\",\"code\":\"dept\",\"type\":\"APPROVAL\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCreateOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"SIGN\",\"timeout\":0,\"id\":\"0d6638e9-0f98-45de-a5ad-8d55702158f7\",\"width\":200,\"height\":45}},{\"id\":\"c4f8dd1b-53f2-4a87-8f57-9828b79fc4d0\",\"type\":\"over-node\",\"x\":918,\"y\":773,\"properties\":{\"name\":\"结束节点\",\"code\":\"over\",\"type\":\"OVER\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCreateOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"c4f8dd1b-53f2-4a87-8f57-9828b79fc4d0\",\"width\":200,\"height\":45}},{\"id\":\"ed654f48-c94c-4fdd-9b14-91f6295ae17a\",\"type\":\"node-node\",\"x\":1227,\"y\":530,\"properties\":{\"name\":\"老板审批\",\"code\":\"boss\",\"type\":\"APPROVAL\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCreateOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"SIGN\",\"timeout\":0,\"id\":\"ed654f48-c94c-4fdd-9b14-91f6295ae17a\",\"width\":200,\"height\":45}}],\"edges\":[{\"id\":\"6854a4ef-89cf-48d3-9aa7-af1e5b87e93c\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":2,\"back\":false},\"sourceNodeId\":\"e7699cab-e20b-4606-af66-fb8d782fd0f8\",\"targetNodeId\":\"0d6638e9-0f98-45de-a5ad-8d55702158f7\",\"startPoint\":{\"x\":1005,\"y\":175.5},\"endPoint\":{\"x\":722,\"y\":369.5},\"pointsList\":[{\"x\":1005,\"y\":175.5},{\"x\":1005,\"y\":275.5},{\"x\":722,\"y\":269.5},{\"x\":722,\"y\":369.5}]},{\"id\":\"7c2c01fc-ded1-46e7-baf7-9fa664898d74\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"0d6638e9-0f98-45de-a5ad-8d55702158f7\",\"targetNodeId\":\"c4f8dd1b-53f2-4a87-8f57-9828b79fc4d0\",\"startPoint\":{\"x\":722,\"y\":414.5},\"endPoint\":{\"x\":918,\"y\":750.5},\"pointsList\":[{\"x\":722,\"y\":414.5},{\"x\":722,\"y\":514.5},{\"x\":918,\"y\":650.5},{\"x\":918,\"y\":750.5}]},{\"id\":\"67ee0fe7-b88c-4fde-be82-e23276f567e6\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"e7699cab-e20b-4606-af66-fb8d782fd0f8\",\"targetNodeId\":\"ed654f48-c94c-4fdd-9b14-91f6295ae17a\",\"startPoint\":{\"x\":1005,\"y\":175.5},\"endPoint\":{\"x\":1227,\"y\":507.5},\"pointsList\":[{\"x\":1005,\"y\":175.5},{\"x\":1005,\"y\":275.5},{\"x\":1227,\"y\":407.5},{\"x\":1227,\"y\":507.5}]},{\"id\":\"9c6f3b0c-03f5-46eb-be39-c79528a824dc\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"ed654f48-c94c-4fdd-9b14-91f6295ae17a\",\"targetNodeId\":\"c4f8dd1b-53f2-4a87-8f57-9828b79fc4d0\",\"startPoint\":{\"x\":1227,\"y\":552.5},\"endPoint\":{\"x\":918,\"y\":750.5},\"pointsList\":[{\"x\":1227,\"y\":552.5},{\"x\":1227,\"y\":652.5},{\"x\":918,\"y\":650.5},{\"x\":918,\"y\":750.5}]}]}"; + String script = "{\"nodes\":[{\"id\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"type\":\"start-node\",\"x\":593,\"y\":96,\"properties\":{\"name\":\"开始节点\",\"code\":\"start\",\"type\":\"START\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"type\":\"node-node\",\"x\":620,\"y\":239,\"properties\":{\"name\":\"流程节点\",\"code\":\"flow\",\"type\":\"APPROVAL\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '8899-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"SIGN\",\"timeout\":10,\"id\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"custom\",\"errTriggerType\":\"custom\"}},{\"id\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"type\":\"over-node\",\"x\":828,\"y\":582,\"properties\":{\"name\":\"结束节点\",\"code\":\"over\",\"type\":\"OVER\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"type\":\"circulate-node\",\"x\":839,\"y\":409,\"properties\":{\"name\":\"抄送节点\",\"code\":\"circulate\",\"type\":\"CIRCULATE\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCreateOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"CIRCULATE\",\"timeout\":0,\"id\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"width\":200,\"height\":45}}],\"edges\":[{\"id\":\"b68837fb-dca8-41d2-908c-dc079a7f61de\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"targetNodeId\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"startPoint\":{\"x\":593,\"y\":118.5},\"endPoint\":{\"x\":620,\"y\":216.5},\"pointsList\":[{\"x\":593,\"y\":118.5},{\"x\":593,\"y\":218.5},{\"x\":620,\"y\":116.5},{\"x\":620,\"y\":216.5}]},{\"id\":\"73e04b95-50f6-44cc-a960-d3007d27fd48\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":2,\"back\":false},\"sourceNodeId\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"targetNodeId\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"startPoint\":{\"x\":720,\"y\":239},\"endPoint\":{\"x\":739,\"y\":409},\"pointsList\":[{\"x\":720,\"y\":239},{\"x\":820,\"y\":239},{\"x\":639,\"y\":409},{\"x\":739,\"y\":409}]},{\"id\":\"f6929c79-b168-4c3c-9f8f-9dc21fcaf29d\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"targetNodeId\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"startPoint\":{\"x\":839,\"y\":431.5},\"endPoint\":{\"x\":828,\"y\":559.5},\"pointsList\":[{\"x\":839,\"y\":431.5},{\"x\":839,\"y\":531.5},{\"x\":828,\"y\":459.5},{\"x\":828,\"y\":559.5}]}]}"; FlowWork flowWork = FlowWorkBuilder.builder(user) .title("请假流程") .schema(script) .build(); assertEquals("请假流程", flowWork.getTitle()); assertEquals(4, flowWork.getNodes().size()); - assertEquals(4, flowWork.getRelations().size()); + assertEquals(3, flowWork.getRelations().size()); FlowNode startNode = flowWork.getStartNode(); @@ -31,7 +32,7 @@ void copy() { assertEquals("请假流程", copyWork.getTitle()); assertEquals(4, copyWork.getNodes().size()); - assertEquals(4, copyWork.getRelations().size()); + assertEquals(3, copyWork.getRelations().size()); copyWork.verify(); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptTest.java index d2f9d9e7..7f1abf00 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptTest.java @@ -52,7 +52,7 @@ void test() { long now = System.currentTimeMillis(); Leave leave = new Leave("我要请假"); - FlowSession flowSession = new FlowSession(flowWork, flowWork.getNodeByCode("start"), user, user, leave, Opinion.pass("同意"),new ArrayList<>()); + FlowSession flowSession = new FlowSession(null,flowWork, flowWork.getNodeByCode("start"), user, user, leave, Opinion.pass("同意"),new ArrayList<>()); List ids = matcher.matcher(flowSession); assertTrue(ids.contains(user.getUserId())); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java index d5128b83..c0a02b51 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java @@ -61,7 +61,7 @@ void unSignTest(){ .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),caocao.getUserId(),lvBu.getUserId(),zhaoYun.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -104,21 +104,18 @@ void unSignTest(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent();; - assertEquals(7, records.size()); + assertEquals(6, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(7, records.size()); + assertEquals(6, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); + assertEquals(4, snapshots.size()); } @@ -154,7 +151,7 @@ void signTest(){ .node("部门领导审批", "dept", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),caocao.getUserId(),lvBu.getUserId(),zhaoYun.getUserId())) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -226,21 +223,18 @@ void signTest(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(7, records.size()); + assertEquals(6, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(7, records.size()); + assertEquals(6, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(8, snapshots.size()); + assertEquals(7, snapshots.size()); } @@ -283,7 +277,7 @@ void signRejectTest(){ zhaoYun.getUserId() )) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.creatorOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("部门领导审批", "start", "dept") .relation("总经理审批", "dept", "manager") @@ -395,21 +389,18 @@ void signRejectTest(){ // 查看所有流程 List records = flowRecordRepository.findAll(pageRequest).getContent();; - assertEquals(12, records.size()); + assertEquals(11, records.size()); userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(0, userTodos.size()); records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(12, records.size()); + assertEquals(11, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(13, snapshots.size()); + assertEquals(12, snapshots.size()); } } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/TrySubmitTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/TrySubmitTest.java new file mode 100644 index 00000000..594201d6 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/TrySubmitTest.java @@ -0,0 +1,134 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.pojo.FlowSubmitResult; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class TrySubmitTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository,userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository,flowProcessRepository,flowBackupRepository); + + /** + * 预提交测试 + */ + @Test + void test() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备", lorne); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + FlowSubmitResult flowSubmitResult = flowService.trySubmitFlow(workCode, user, leave, Opinion.pass("发起流程")); + // 下级审批人有1个 + assertEquals(1, flowSubmitResult.getOperators().size()); + // 下级审批人是刘备 + assertEquals(dept.getUserId(), flowSubmitResult.getOperators().get(0).getUserId()); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + + flowSubmitResult = flowService.trySubmitFlow(userTodos.get(0).getId(), user, leave, Opinion.pass("同意")); + // 下级审批人有1个 + assertEquals(1, flowSubmitResult.getOperators().size()); + // 下级审批人是刘备 + assertEquals(dept.getUserId(), flowSubmitResult.getOperators().get(0).getUserId()); + + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + List lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + // 提交委托lorne部门经理的审批 + FlowRecord lorneTodo = lorneTodos.get(0); + flowService.submitFlow(lorneTodo.getId(), lorne, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + + } + +} diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 62c748bd..a29f9191 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.6 + 2.9.7 springboot-starter-security diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java index c0ecc62b..b7fa3f61 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java @@ -73,7 +73,7 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR LoginRequest loginRequest = LoginRequestContext.getInstance().get(); Token token = tokenGateway.create(user.getUsername(), loginRequest.getPassword(), - user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()), + user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.collect(Collectors.toList())), TokenContext.getExtra()); LoginResponse loginResponse = loginHandler.postHandle(request, response, loginRequest, user, token); diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index e1440db2..085b55f7 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.6 + 2.9.7 springboot-starter From ed2bc28c4d9c22c87719317ccd14313ce174a490 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 5 Dec 2024 23:55:33 +0800 Subject: [PATCH 063/129] update flow --- .../com/codingapi/springboot/security/filter/MyLoginFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java index b7fa3f61..c0ecc62b 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/MyLoginFilter.java @@ -73,7 +73,7 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR LoginRequest loginRequest = LoginRequestContext.getInstance().get(); Token token = tokenGateway.create(user.getUsername(), loginRequest.getPassword(), - user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.collect(Collectors.toList())), + user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()), TokenContext.getExtra()); LoginResponse loginResponse = loginHandler.postHandle(request, response, loginRequest, user, token); From 84d96a9e0a06e41fb9da51bb221f55b6dd9b6ff6 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 5 Dec 2024 23:56:49 +0800 Subject: [PATCH 064/129] update flow --- .../springboot/fast/jpa/repository/DynamicSQLBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java index eb2a15c8..caa1a9d7 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java @@ -45,7 +45,7 @@ public String getHQL() { Sort sort = request.getSort(); if (sort.isSorted()) { hql.append(" ORDER BY "); - List orders = sort.collect(Collectors.toList()); + List orders = sort.toList(); for (int i = 0; i < orders.size(); i++) { Sort.Order order = orders.get(i); hql.append(order.getProperty()).append(" ").append(order.getDirection().name()); From 004a90e9b5b39955259511e14209dfc1d6fe6f1b Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 6 Dec 2024 14:58:30 +0800 Subject: [PATCH 065/129] add not equal --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../jpa/repository/DynamicSQLBuilder.java | 7 +++++++ .../springboot/fast/DemoRepositoryTest.java | 19 +++++++++++++++++++ springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/dto/request/Filter.java | 4 ++++ .../framework/dto/request/Relation.java | 1 + .../framework/dto/request/SearchRequest.java | 12 +++++++----- 10 files changed, 43 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index f9d62149..d6657389 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.7 + 2.9.8 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index b2efbee5..f9d3a1bc 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.7 + 2.9.8 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java index caa1a9d7..68052924 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java @@ -98,6 +98,13 @@ private void buildSQL(Filter filter, StringBuilder hql) { params.add(filter.getValue()[0]); paramIndex++; } + + if (filter.isNotEqual()) { + hql.append(filter.getKey()).append(" != ?").append(paramIndex); + params.add(filter.getValue()[0]); + paramIndex++; + } + if (filter.isLike()) { hql.append(filter.getKey()).append(" LIKE ?").append(paramIndex); params.add("%" + filter.getValue()[0] + "%"); diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index cb2ea09b..236f1d51 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -56,6 +56,25 @@ void findAll() { assertEquals(1, page.getTotalElements()); } + @Test + void pageRequestNotEqual() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demo1 = demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + PageRequest request = new PageRequest(); + request.setCurrent(1); + request.setPageSize(10); + request.addFilter("id", Relation.NOT_EQUAL, demo1.getId()); + + Page page = demoRepository.pageRequest(request); + assertEquals(1, page.getTotalElements()); + } @Test void pageRequest() { diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 4aac3f3a..dee247fc 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.7 + 2.9.8 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index a29f9191..a0927f82 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.7 + 2.9.8 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 085b55f7..2d32b141 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.7 + 2.9.8 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java index 723448d5..319a916a 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java @@ -48,6 +48,10 @@ public boolean isEqual() { return relation == Relation.EQUAL; } + public boolean isNotEqual() { + return relation == Relation.NOT_EQUAL; + } + public boolean isLike() { return relation == Relation.LIKE; } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java index 7941a3c4..0bd900dd 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java @@ -2,6 +2,7 @@ public enum Relation { + NOT_EQUAL, EQUAL, LIKE, LEFT_LIKE, diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java index f559812b..f14539ae 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java @@ -224,11 +224,13 @@ public PageRequest toPageRequest(Class clazz) { if (JSON.isValid(filter)) { removeKeys.add("filter"); JSONObject jsonObject = JSON.parseObject(filter); - for (String key : jsonObject.keySet()) { - JSONArray value = jsonObject.getJSONArray(key); - if (value != null && !value.isEmpty()) { - List values = value.stream().map(Object::toString).collect(Collectors.toList()); - content.addFilter(key, values); + if(jsonObject!=null) { + for (String key : jsonObject.keySet()) { + JSONArray value = jsonObject.getJSONArray(key); + if (value != null && !value.isEmpty()) { + List values = value.stream().map(Object::toString).collect(Collectors.toList()); + content.addFilter(key, values); + } } } } From 06df1b29c6416e0fa32d44c3d7fa78562c854397 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 6 Dec 2024 22:12:10 +0800 Subject: [PATCH 066/129] fix trySubmitFlow bug --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/domain/FlowNode.java | 22 ++- .../flow/matcher/OperatorMatcher.java | 11 ++ .../flow/service/FlowDirectionService.java | 7 +- .../flow/service/impl/FlowSubmitService.java | 4 +- .../service/impl/FlowTrySubmitService.java | 10 +- .../springboot/flow/test/SignTest.java | 141 ++++++++++++++++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 11 files changed, 184 insertions(+), 21 deletions(-) diff --git a/pom.xml b/pom.xml index d6657389..1afb88ba 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.8 + 2.9.9 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index f9d3a1bc..c08748f4 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.8 + 2.9.9 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index dee247fc..c63624fb 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.8 + 2.9.9 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java index 28342d75..37bc95ec 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java @@ -19,7 +19,9 @@ import lombok.Setter; import org.springframework.util.StringUtils; +import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; /** * 流程节点 @@ -101,21 +103,30 @@ public class FlowNode { */ private List buttons; + /** + * 按钮顺序 + */ + public List getButtons() { + if (buttons != null) { + return buttons.stream().sorted(Comparator.comparingInt(FlowButton::getOrder)).collect(Collectors.toList()); + } + return null; + } - public void verify(){ + public void verify() { if (this.titleGenerator == null) { throw new IllegalArgumentException("titleGenerator is null"); } if (this.operatorMatcher == null) { throw new IllegalArgumentException("operatorMatcher is null"); } - if(timeout<0){ + if (timeout < 0) { throw new IllegalArgumentException("timeout is less than 0"); } - if(!StringUtils.hasLength(id)){ + if (!StringUtils.hasLength(id)) { throw new IllegalArgumentException("id is empty"); } - if(!StringUtils.hasLength(code)){ + if (!StringUtils.hasLength(code)) { throw new IllegalArgumentException("code is empty"); } } @@ -206,8 +217,7 @@ public FlowRecord createRecord(long workId, String title, IFlowOperator createOperator, IFlowOperator currentOperator, - BindDataSnapshot snapshot - ) { + BindDataSnapshot snapshot) { // 当前操作者存在委托人时,才需要寻找委托人 IFlowOperator flowOperator = currentOperator; diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java index 950f950e..9580251f 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java @@ -85,6 +85,17 @@ public static OperatorMatcher specifyOperatorMatcher(long... userIds) { return new OperatorMatcher("def run(content) {return [" + userIdsStr + "];}", STATE_SPECIFY); } + /** + * 指定操作者匹配器 + * + * @param userIds 用户ids + * @return 操作者匹配器 + */ + public static OperatorMatcher specifyOperatorMatcher(List userIds) { + String userIdsStr = userIds.stream().map(String::valueOf).collect(Collectors.joining(",")); + return new OperatorMatcher("def run(content) {return [" + userIdsStr + "];}", STATE_SPECIFY); + } + /** * 创建者操作者匹配器 * diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java index 3b8f3aac..829238bb 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java @@ -81,12 +81,7 @@ public void verifyFlowSourceDirection() { */ public boolean hasCurrentFlowNodeIsDone() { // 会签下所有人尚未提交时,不执行下一节点 - boolean allDone = historyRecords.stream().filter(item -> !item.isTransfer()).allMatch(FlowRecord::isDone); - if (!allDone) { - // 流程尚未审批结束直接退出 - return true; - } - return false; + return historyRecords.stream().filter(item -> !item.isTransfer()).allMatch(FlowRecord::isDone); } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index 77d379c6..3f1b1136 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -98,8 +98,8 @@ public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBind // 判断流程是否结束(会签时需要所有人都通过) if (flowNode.isSign()) { - boolean next = flowDirectionService.hasCurrentFlowNodeIsDone(); - if (next) { + boolean isDone = flowDirectionService.hasCurrentFlowNodeIsDone(); + if (!isDone) { List todoRecords = historyRecords.stream().filter(FlowRecord::isTodo).collect(Collectors.toList()); return new FlowResult(flowWork, todoRecords); } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java index c48fab7f..d80ed9f4 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java @@ -108,13 +108,19 @@ private FlowSubmitResult trySubmitFlow(FlowWork flowWork, FlowNode flowNode, Flo } else { // copy 流程数据防止影响原有数据 historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()).stream().map(FlowRecord::copy).collect(Collectors.toList()); + // 更新当前流程记录, 由于try测试过程中没有对数据落库,所以这里需要手动更新 + for(FlowRecord record : historyRecords){ + if(record.getId() == flowRecord.getId()){ + record.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); + } + } } flowDirectionService.bindHistoryRecords(historyRecords); // 判断流程是否结束(会签时需要所有人都通过) if (flowNode.isSign()) { - boolean next = flowDirectionService.hasCurrentFlowNodeIsDone(); - if (next) { + boolean isDone = flowDirectionService.hasCurrentFlowNodeIsDone(); + if (!isDone) { List todoRecords = historyRecords.stream().filter(FlowRecord::isTodo).collect(Collectors.toList()); return new FlowSubmitResult(flowWork, flowNode, todoRecords.stream().map(FlowRecord::getCurrentOperator).collect(Collectors.toList())); } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java index c0a02b51..c4073ceb 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java @@ -7,14 +7,18 @@ import com.codingapi.springboot.flow.em.ApprovalType; import com.codingapi.springboot.flow.flow.Leave; import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.pojo.FlowSubmitResult; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.*; import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.IFlowOperator; import com.codingapi.springboot.flow.user.User; import org.junit.jupiter.api.Test; import org.springframework.data.domain.PageRequest; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -403,4 +407,141 @@ void signRejectTest(){ assertEquals(12, snapshots.size()); } + + + + /** + * 多人会签trySubmit测试 + */ + @Test + void signTrySubmitTest(){ + PageRequest pageRequest = PageRequest.of(0, 1000); + + User caocao = new User("曹操"); + userRepository.save(caocao); + User lvBu = new User("吕布"); + userRepository.save(lvBu); + User zhaoYun = new User("赵云"); + userRepository.save(zhaoYun); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + List signUsers = new ArrayList<>(); + signUsers.add(dept); + signUsers.add(caocao); + signUsers.add(lvBu); + signUsers.add(zhaoYun); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(signUsers.stream().map(User::getUserId).collect(Collectors.toList()))) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN,OperatorMatcher.specifyOperatorMatcher(boss.getUserId()) ) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + + // 验证会签的人员 + FlowSubmitResult submitResult = flowService.trySubmitFlow(userTodo.getId(), user, leave, Opinion.pass("用户同意")); + List operators = submitResult.getOperators(); + assertEquals(signUsers.size(), operators.size()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("用户同意").specify(dept.getUserId())); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + + // 验证会签的人员 + submitResult = flowService.trySubmitFlow(deptTodo.getId(), dept, leave, Opinion.pass("用户同意")); + operators = submitResult.getOperators(); + assertEquals(1, operators.size()); + assertEquals(boss.getName(), operators.get(0).getName()); + + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("刘备同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + +// // 查看部门经理 吕布 的待办 +// List lvbuTodos = flowRecordRepository.findTodoByOperatorId(lvBu.getUserId(), pageRequest).getContent(); +// assertEquals(1, lvbuTodos.size()); +// +// // 提交部门经理 吕布 的审批 +// FlowRecord lvbuTodo = lvbuTodos.get(0); +// flowService.submitFlow(lvbuTodo.getId(), lvBu, leave, Opinion.pass("吕布同意")); +// +// +// // 查看部门经理 赵云 的待办 +// List zhaoYunTodos = flowRecordRepository.findTodoByOperatorId(zhaoYun.getUserId(), pageRequest).getContent(); +// assertEquals(1, zhaoYunTodos.size()); +// +// // 提交部门经理 赵云 的审批 +// FlowRecord zhaoYunTodo = zhaoYunTodos.get(0); +// flowService.submitFlow(zhaoYunTodo.getId(), zhaoYun, leave, Opinion.pass("赵云同意")); +// +// +// // 查看部门经理 曹操 的待办 +// List caocaoTodos = flowRecordRepository.findTodoByOperatorId(caocao.getUserId(), pageRequest).getContent(); +// assertEquals(1, caocaoTodos.size()); +// +// // 提交部门经理 曹操 的审批 +// FlowRecord caocaoTodo = caocaoTodos.get(0); +// flowService.submitFlow(caocaoTodo.getId(), caocao, leave, Opinion.pass("曹操同意")); +// +// bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); +// assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + + } } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index a0927f82..6da8d47d 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.8 + 2.9.9 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 2d32b141..8defe7d2 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.8 + 2.9.9 springboot-starter From cdd6060d905fd0e8db2e32af85ea7b51526a1d20 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 7 Dec 2024 15:41:01 +0800 Subject: [PATCH 067/129] add springboot-parent --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/content/FlowSession.java | 13 +++++++++++++ .../codingapi/springboot/flow/pojo/FlowDetail.java | 4 ++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 7 files changed, 22 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 1afb88ba..5ad4e087 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.9 + 2.9.10 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index c08748f4..d72e4f33 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.9 + 2.9.10 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index c63624fb..393787de 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.9 + 2.9.10 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java index be9cf44e..515d42d9 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java @@ -65,6 +65,19 @@ public Object getBean(String beanName) { return provider.getBean(beanName); } + + + /** + * 获取审批意见 + */ + public String getAdvice() { + if (opinion != null) { + return opinion.getAdvice(); + } else { + return null; + } + } + /** * 创建节点结果 * diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java index a8f2be0f..1b73841f 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java @@ -103,10 +103,14 @@ public FlowDetail(FlowWork flowWork, public final class FlowOpinion { private final long recordId; private final Opinion opinion; + private final String nodeCode; + private final String nodeName; private final IFlowOperator operator; private final long createTime; public FlowOpinion(FlowRecord flowRecord) { + this.nodeCode = flowRecord.getNodeCode(); + this.nodeName = flowWork.getNodeByCode(nodeCode).getName(); this.recordId = flowRecord.getId(); this.opinion = flowRecord.getOpinion(); this.operator = flowRecord.getCurrentOperator(); diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 6da8d47d..24e143e5 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.9 + 2.9.10 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 8defe7d2..b68aae75 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.9 + 2.9.10 springboot-starter From 609225bc970fa523e65b1b65adcd8c31cdf2609b Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 9 Dec 2024 23:36:04 +0800 Subject: [PATCH 068/129] add 2.9.11 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../com/codingapi/springboot/flow/domain/FlowButton.java | 6 ++++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 5ad4e087..e1075e7e 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.10 + 2.9.11 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index d72e4f33..9fb04bc0 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.10 + 2.9.11 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 393787de..f20faf76 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.10 + 2.9.11 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowButton.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowButton.java index 6bd5c440..7dd5d8e5 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowButton.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowButton.java @@ -39,6 +39,12 @@ public class FlowButton { * 自定义事件内容 (后端脚本) */ private String groovy; + + /** + * 自定义事件内容 (前端脚本) + */ + private String eventKey; + /** * 排序 */ diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 24e143e5..be776c43 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.10 + 2.9.11 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index b68aae75..08ed1384 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.10 + 2.9.11 springboot-starter From 3d0eaa626362b2e62ea6261951e150f3da81d660 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 10 Dec 2024 11:51:43 +0800 Subject: [PATCH 069/129] fix resetToken --- .../security/redis/RedisTokenGateway.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java index d4eb4257..e38c573d 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java @@ -38,10 +38,26 @@ public Token parser(String sign) { return JSONObject.parseObject(json, Token.class); } + /** + * 删除token + * @param token token + */ public void removeToken(String token) { redisTemplate.delete(token); } + /** + * 重置token + * @param token token + */ + public void resetToken(Token token){ + redisTemplate.opsForValue().set(token.getToken(), token.toJson(), validTime, TimeUnit.MILLISECONDS); + } + + /** + * 删除用户 + * @param username 用户名 + */ public void removeUsername(String username) { Set keys = redisTemplate.keys(username + ":*"); if (keys != null && !keys.isEmpty()) { @@ -49,6 +65,11 @@ public void removeUsername(String username) { } } + /** + * 自定义删除用户 + * @param username 用户名 + * @param predicate 条件 + */ public void removeUsername(String username, Predicate predicate) { Set keys = redisTemplate.keys(username + ":*"); if (keys != null && !keys.isEmpty()) { From c2c22883455a531b3ccedfaf137a1e8f91256ac2 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 10 Dec 2024 11:52:12 +0800 Subject: [PATCH 070/129] fix resetToken --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index e1075e7e..1cb9195f 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.11 + 2.9.12 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 9fb04bc0..a400c560 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.11 + 2.9.12 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index f20faf76..861a55c4 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.11 + 2.9.12 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index be776c43..e2099d17 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.11 + 2.9.12 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 08ed1384..dd76d533 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.11 + 2.9.12 springboot-starter From ab6ef03f9443614853ebdc9326ac08653bd6785e Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 10 Dec 2024 16:11:12 +0800 Subject: [PATCH 071/129] fix resetToken --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- .../security/redis/RedisTokenGateway.java | 38 +++++++++++++++---- .../security/redis/RedisTokenGatewayImpl.java | 2 +- springboot-starter/pom.xml | 2 +- 7 files changed, 37 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index 1cb9195f..36b24408 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.12 + 2.9.13 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index a400c560..9ef218ad 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.12 + 2.9.13 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 861a55c4..a39352ed 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.12 + 2.9.13 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index e2099d17..68bef439 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.12 + 2.9.13 springboot-starter-security diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java index e38c573d..0e7d69f0 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java @@ -4,6 +4,7 @@ import com.codingapi.springboot.security.gateway.Token; import org.springframework.data.redis.core.RedisTemplate; +import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.UUID; @@ -30,8 +31,14 @@ public Token create(String username, String iv, List authorities, String return token; } - public Token parser(String sign) { - String json = redisTemplate.opsForValue().get(sign); + /** + * 根据token获取用户信息 + * + * @param token token + * @return 用户信息 + */ + public Token getToken(String token) { + String json = redisTemplate.opsForValue().get(token); if (json == null) { return null; } @@ -40,6 +47,7 @@ public Token parser(String sign) { /** * 删除token + * * @param token token */ public void removeToken(String token) { @@ -48,33 +56,49 @@ public void removeToken(String token) { /** * 重置token + * * @param token token */ - public void resetToken(Token token){ + public void resetToken(Token token) { redisTemplate.opsForValue().set(token.getToken(), token.toJson(), validTime, TimeUnit.MILLISECONDS); } /** * 删除用户 + * * @param username 用户名 */ public void removeUsername(String username) { Set keys = redisTemplate.keys(username + ":*"); - if (keys != null && !keys.isEmpty()) { + if (!keys.isEmpty()) { redisTemplate.delete(keys); } } + /** - * 自定义删除用户 + * 获取用户的所有token + * * @param username 用户名 + * @return token列表 + */ + public List getTokensByUsername(String username) { + Set keys = redisTemplate.keys(username + ":*"); + return new ArrayList<>(keys); + } + + + /** + * 自定义删除用户 + * + * @param username 用户名 * @param predicate 条件 */ public void removeUsername(String username, Predicate predicate) { Set keys = redisTemplate.keys(username + ":*"); - if (keys != null && !keys.isEmpty()) { + if (!keys.isEmpty()) { for (String key : keys) { - Token token = parser(key); + Token token = getToken(key); if (token != null && predicate.test(token)) { redisTemplate.delete(key); } diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGatewayImpl.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGatewayImpl.java index 19453d66..8973f26d 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGatewayImpl.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGatewayImpl.java @@ -20,7 +20,7 @@ public Token create(String username, String iv, List authorities, String @Override public Token parser(String sign) { - return redisTokenGateway.parser(sign); + return redisTokenGateway.getToken(sign); } } diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index dd76d533..83d8f939 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.12 + 2.9.13 springboot-starter From dfff4a84697924647e4bfbe7803b44c54cb25a1e Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 12 Dec 2024 09:46:26 +0800 Subject: [PATCH 072/129] add 2.9.14 --- pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/annotation/ColumnType.java | 47 +++++++++++++++++++ .../framework/annotation/MetaColumn.java | 43 +++++++++++++++++ .../framework/annotation/MetaRelation.java | 20 ++++++++ .../framework/annotation/MetaTable.java | 23 +++++++++ .../src/main/resources/META-INF/banner.txt | 4 ++ 10 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/ColumnType.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaColumn.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaRelation.java create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaTable.java create mode 100644 springboot-starter/src/main/resources/META-INF/banner.txt diff --git a/pom.xml b/pom.xml index 36b24408..69009d6e 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 2.9.13 + 2.9.14 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 9ef218ad..8d142d1e 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.13 + 2.9.14 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index a39352ed..b5fadf19 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.13 + 2.9.14 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 68bef439..0357b2d4 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.13 + 2.9.14 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 83d8f939..d8c0d844 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.13 + 2.9.14 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/ColumnType.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/ColumnType.java new file mode 100644 index 00000000..215814c1 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/ColumnType.java @@ -0,0 +1,47 @@ +package com.codingapi.springboot.framework.annotation; + +/** + * 数据库字段类型 + */ +public enum ColumnType { + + /** + * 整数 + */ + Number, + + /** + * 浮点数 + */ + Float, + + /** + * 字符串 + */ + String, + + /** + * 日期 + */ + Date, + + /** + * 文件 + */ + File, + + /** + * 布尔 + */ + Boolean, + + /** + * 字节 + */ + Bytes, + + /** + * JSON + */ + JSON, +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaColumn.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaColumn.java new file mode 100644 index 00000000..289a1d04 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaColumn.java @@ -0,0 +1,43 @@ +package com.codingapi.springboot.framework.annotation; + +import java.lang.annotation.*; + +/** + * 查询字段 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface MetaColumn { + + /** + * 字段说明 + */ + String desc(); + + /** + * 字段名称 + */ + String name(); + + /** + * 是否主键 + */ + boolean primaryKey() default false; + + /** + * 字段类型 + */ + ColumnType type() default ColumnType.String; + + /** + * 格式化 + */ + String format() default ""; + + /** + * 依赖表 + */ + MetaRelation dependent() default @MetaRelation(tableName = "", columnName = ""); + +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaRelation.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaRelation.java new file mode 100644 index 00000000..2ee40710 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaRelation.java @@ -0,0 +1,20 @@ +package com.codingapi.springboot.framework.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface MetaRelation { + + /** + * 表名称 + */ + String tableName(); + + /** + * 字段名称 + */ + String columnName(); +} diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaTable.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaTable.java new file mode 100644 index 00000000..6075b1eb --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/MetaTable.java @@ -0,0 +1,23 @@ +package com.codingapi.springboot.framework.annotation; + +import java.lang.annotation.*; + +/** + * 查询表 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface MetaTable { + + /** + * 表说明 + */ + String desc(); + + /** + * 表名称 + */ + String name(); + +} diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt new file mode 100644 index 00000000..23fb5d83 --- /dev/null +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -0,0 +1,4 @@ +------------------------------------------------------ +CodingApi SpringBoot-Starter 2.9.14 +springboot version (${spring-boot.version}) +------------------------------------------------------ From 6ee0ebe63584b1762acd9ccdfd23db034a740d13 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 19 Dec 2024 09:59:22 +0800 Subject: [PATCH 073/129] add springboot-starter-data-authorization --- README.md | 8 + pom.xml | 21 +- springboot-starter-data-authorization/pom.xml | 77 ++ .../DataAuthorizationConfiguration.java | 48 + .../DataAuthorizationContext.java | 81 ++ .../enhancer/DataPermissionSQLEnhancer.java | 110 ++ .../enhancer/TableColumnAlias.java | 62 + .../enhancer/TableColumnAliasContext.java | 92 ++ .../enhancer/TableColumnAliasHolder.java | 115 ++ .../exception/NotAuthorizationException.java | 13 + .../filter/DataAuthorizationFilter.java | 44 + .../DefaultDataAuthorizationFilter.java | 27 + .../authorization/handler/ColumnHandler.java | 74 + .../handler/ColumnHandlerContext.java | 144 ++ .../authorization/handler/Condition.java | 33 + .../handler/DefaultColumnHandler.java | 161 +++ .../handler/DefaultRowHandler.java | 11 + .../authorization/handler/RowHandler.java | 19 + .../handler/RowHandlerContext.java | 18 + .../interceptor/DataPermissionSQL.java | 18 + .../interceptor/DefaultSQLInterceptor.java | 35 + .../interceptor/SQLInterceptState.java | 60 + .../interceptor/SQLInterceptor.java | 39 + .../interceptor/SQLInterceptorContext.java | 20 + .../interceptor/SQLRunningContext.java | 67 + .../jdbc/AuthorizationJdbcDriver.java | 57 + .../jdbc/proxy/CallableStatementProxy.java | 1191 +++++++++++++++++ .../jdbc/proxy/ConnectionProxy.java | 300 +++++ .../jdbc/proxy/PreparedStatementProxy.java | 585 ++++++++ .../jdbc/proxy/ResultSetProxy.java | 1180 ++++++++++++++++ .../jdbc/proxy/StatementProxy.java | 290 ++++ .../authorization/mask/ColumnMask.java | 12 + .../authorization/mask/ColumnMaskContext.java | 34 + .../authorization/mask/impl/BankCardMask.java | 43 + .../authorization/mask/impl/IDCardMask.java | 29 + .../authorization/mask/impl/PhoneMask.java | 31 + .../DataAuthorizationProperties.java | 17 + .../DataAuthorizationPropertyContext.java | 24 + .../register/ConditionHandlerRegister.java | 14 + .../DataAuthorizationContextRegister.java | 17 + .../register/ResultSetHandlerRegister.java | 15 + .../register/SQLInterceptorRegister.java | 14 + .../authorization/utils/SQLUtils.java | 25 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../DataAuthorizationContextTest.java | 378 ++++++ .../DataAuthorizationTestApplication.java | 13 + .../analyzer/SelectSQLAnalyzerTest.java | 198 +++ .../authorization/current/CurrentUser.java | 27 + .../authorization/entity/Depart.java | 38 + .../springboot/authorization/entity/Unit.java | 34 + .../springboot/authorization/entity/User.java | 49 + .../mask/impl/BankCardMaskTest.java | 17 + .../mask/impl/IDCardMaskTest.java | 16 + .../mask/impl/PhoneMaskTest.java | 17 + .../repository/DepartRepository.java | 8 + .../repository/UnitRepository.java | 8 + .../repository/UserRepository.java | 12 + .../src/test/resources/application.properties | 13 + springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 63 files changed, 6105 insertions(+), 9 deletions(-) create mode 100644 springboot-starter-data-authorization/pom.xml create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationConfiguration.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationContext.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAlias.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAliasContext.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAliasHolder.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/exception/NotAuthorizationException.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/filter/DataAuthorizationFilter.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/filter/DefaultDataAuthorizationFilter.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/ColumnHandler.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/ColumnHandlerContext.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/Condition.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/DefaultColumnHandler.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/DefaultRowHandler.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/RowHandler.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/RowHandlerContext.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DataPermissionSQL.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DefaultSQLInterceptor.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptState.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptor.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptorContext.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLRunningContext.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/CallableStatementProxy.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/ConnectionProxy.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/PreparedStatementProxy.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/ResultSetProxy.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/StatementProxy.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/ColumnMask.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/ColumnMaskContext.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/BankCardMask.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/IDCardMask.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/PhoneMask.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/properties/DataAuthorizationProperties.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/properties/DataAuthorizationPropertyContext.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/ConditionHandlerRegister.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/DataAuthorizationContextRegister.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/ResultSetHandlerRegister.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/SQLInterceptorRegister.java create mode 100644 springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/utils/SQLUtils.java create mode 100644 springboot-starter-data-authorization/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationContextTest.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationTestApplication.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/analyzer/SelectSQLAnalyzerTest.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/current/CurrentUser.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/Depart.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/Unit.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/User.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/BankCardMaskTest.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/IDCardMaskTest.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/PhoneMaskTest.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/DepartRepository.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/UnitRepository.java create mode 100644 springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/UserRepository.java create mode 100644 springboot-starter-data-authorization/src/test/resources/application.properties diff --git a/README.md b/README.md index 68fea27b..74f5fe9a 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ v.3.x 为springboot 3.x版本,使用jdk17版本 * springboot-starter | Springboot领域驱动框架 * springboot-starter-data-fast | 快速数据呈现框架 +* springboot-starter-data-authorization | 数据权限框架 * springboot-starter-flow | 流程引擎框架 * springboot-starter-security | security权限框架支持基于JWT的无状态权限认证与Redis的有状态权限认证 @@ -42,6 +43,13 @@ v.3.x 为springboot 3.x版本,使用jdk17版本 ${last.version} + + + com.codingapi.springboot + springboot-starter-data-authorization + ${last.version} + + com.codingapi.springboot diff --git a/pom.xml b/pom.xml index 69009d6e..3ac27491 100644 --- a/pom.xml +++ b/pom.xml @@ -3,6 +3,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 pom + + springboot-starter-data-authorization + org.springframework.boot spring-boot-starter-parent @@ -12,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.14 + 2.9.15 https://github.com/codingapi/springboot-framewrok springboot-parent @@ -45,6 +48,7 @@ 4.0.24 2.3.232 5.6.2 + 5.0 @@ -209,6 +213,12 @@ ${apache-groovy.version} + + com.github.jsqlparser + jsqlparser + ${jsqlparser.version} + + @@ -269,9 +279,10 @@ springboot-starter - springboot-starter-flow springboot-starter-security + springboot-starter-data-authorization springboot-starter-data-fast + springboot-starter-flow @@ -281,9 +292,10 @@ springboot-starter - springboot-starter-flow springboot-starter-security + springboot-starter-data-authorization springboot-starter-data-fast + springboot-starter-flow @@ -331,9 +343,10 @@ springboot-starter - springboot-starter-flow springboot-starter-security + springboot-starter-data-authorization springboot-starter-data-fast + springboot-starter-flow diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml new file mode 100644 index 00000000..4be50638 --- /dev/null +++ b/springboot-starter-data-authorization/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + springboot-parent + com.codingapi.springboot + 2.9.15 + + + springboot-starter-data-authorization + springboot-starter-data-authorization project for Spring Boot + + + 8 + + + + + + com.github.jsqlparser + jsqlparser + + + + org.springframework.boot + spring-boot-starter-data-jpa + test + + + + org.springframework.boot + spring-boot-starter-data-jdbc + test + + + + com.h2database + h2 + test + + + + com.mysql + mysql-connector-j + test + + + + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.12 + + + + prepare-agent + + + + report + test + + report + + + + + + + + diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationConfiguration.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationConfiguration.java new file mode 100644 index 00000000..e36e604a --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationConfiguration.java @@ -0,0 +1,48 @@ +package com.codingapi.springboot.authorization; + + +import com.codingapi.springboot.authorization.filter.DataAuthorizationFilter; +import com.codingapi.springboot.authorization.handler.ColumnHandler; +import com.codingapi.springboot.authorization.handler.RowHandler; +import com.codingapi.springboot.authorization.interceptor.SQLInterceptor; +import com.codingapi.springboot.authorization.properties.DataAuthorizationProperties; +import com.codingapi.springboot.authorization.register.ConditionHandlerRegister; +import com.codingapi.springboot.authorization.register.DataAuthorizationContextRegister; +import com.codingapi.springboot.authorization.register.ResultSetHandlerRegister; +import com.codingapi.springboot.authorization.register.SQLInterceptorRegister; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.List; + +@Configuration +public class DataAuthorizationConfiguration { + + @Bean + @ConfigurationProperties(prefix = "codingapi.data-authorization") + public DataAuthorizationProperties dataAuthorizationProperties(){ + return new DataAuthorizationProperties(); + } + + @Bean + public ConditionHandlerRegister conditionHandlerRegister(@Autowired(required = false) RowHandler rowHandler) { + return new ConditionHandlerRegister(rowHandler); + } + + @Bean + public ResultSetHandlerRegister resultSetHandlerRegister(@Autowired(required = false) ColumnHandler columnHandler) { + return new ResultSetHandlerRegister(columnHandler); + } + + @Bean + public SQLInterceptorRegister sqlInterceptorRegister(@Autowired(required = false) SQLInterceptor sqlInterceptor) { + return new SQLInterceptorRegister(sqlInterceptor); + } + + @Bean + public DataAuthorizationContextRegister dataAuthorizationContextRegister(@Autowired(required = false) List dataAuthorizationFilters) { + return new DataAuthorizationContextRegister(dataAuthorizationFilters); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationContext.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationContext.java new file mode 100644 index 00000000..9af58d8a --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/DataAuthorizationContext.java @@ -0,0 +1,81 @@ +package com.codingapi.springboot.authorization; + +import com.codingapi.springboot.authorization.filter.DataAuthorizationFilter; +import com.codingapi.springboot.authorization.handler.Condition; +import com.codingapi.springboot.authorization.interceptor.SQLInterceptState; +import lombok.Getter; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 数据权限上下文 + */ +public class DataAuthorizationContext { + + @Getter + private final static DataAuthorizationContext instance = new DataAuthorizationContext(); + + private final List filters; + + private DataAuthorizationContext() { + this.filters = new ArrayList<>(); + } + + /** + * 添加数据权限过滤器 + * @param filter 数据权限过滤器 + */ + public void addDataAuthorizationFilter(DataAuthorizationFilter filter) { + this.filters.add(filter); + } + + /** + * 清空数据权限过滤器 + */ + public void clearDataAuthorizationFilters() { + this.filters.clear(); + } + + /** + * 列权限 + * @param interceptState 拦截状态 + * @param tableName 表名(或别名) + * @param columnName 列名 (或别名) + * @param value 值 + * @return T + * @param 泛型 + */ + public T columnAuthorization(SQLInterceptState interceptState, String tableName, String columnName, T value) { + if (interceptState != null && interceptState.hasIntercept()) { + String realTableName = interceptState.getTableName(tableName); + String realColumnName = interceptState.getColumnName(tableName,columnName); + + for (DataAuthorizationFilter filter : filters) { + if (filter.supportColumnAuthorization(realTableName, realColumnName, value)) { + return filter.columnAuthorization(realTableName, realColumnName, value); + } + } + } + return value; + } + + /** + * 行权限 + * @param tableName 表名 + * @param tableAlias 别名 + * @return Condition 增加的过滤条件 + */ + public Condition rowAuthorization(String tableName, String tableAlias) { + if (StringUtils.hasText(tableName) && StringUtils.hasText(tableAlias)) { + for (DataAuthorizationFilter filter : filters) { + if (filter.supportRowAuthorization(tableName, tableAlias)) { + return filter.rowAuthorization(tableName, tableAlias); + } + } + } + return null; + } + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java new file mode 100644 index 00000000..66a91a6b --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java @@ -0,0 +1,110 @@ +package com.codingapi.springboot.authorization.enhancer; + + +import com.codingapi.springboot.authorization.handler.Condition; +import com.codingapi.springboot.authorization.handler.RowHandler; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.select.FromItem; +import net.sf.jsqlparser.statement.select.Join; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.Select; + +import java.sql.SQLException; + +/** + * 数据权限 SQL 增强器 + */ +public class DataPermissionSQLEnhancer { + + private final String sql; + private final RowHandler rowHandler; + private final TableColumnAliasHolder tableColumnAliasHolder; + private final Statement statement; + + + // 构造函数 + public DataPermissionSQLEnhancer(String sql, RowHandler rowHandler) throws SQLException { + try { + // 如何sql中存在? 则在?后面添加空格 + this.sql = sql.replaceAll("\\?", " ? "); + this.rowHandler = rowHandler; + this.statement = CCJSqlParserUtil.parse(this.sql); + this.tableColumnAliasHolder = new TableColumnAliasHolder(statement); + } catch (Exception e) { + throw new SQLException(e); + } + } + + // 获取增强后的SQL + public String getNewSQL() throws SQLException { + try { + if (statement instanceof Select) { + tableColumnAliasHolder.holderAlias(); + Select select = (Select) statement; + PlainSelect plainSelect = select.getPlainSelect(); + this.enhanceDataPermissionInSelect(plainSelect); + return statement.toString(); + } + } catch (Exception e) { + throw new SQLException(e); + } + return sql; + } + + public TableColumnAliasContext getTableAlias() { + return tableColumnAliasHolder.getAliasContext(); + } + + + // 增强 SELECT 语句 + private void enhanceDataPermissionInSelect(PlainSelect plainSelect) throws Exception { + FromItem fromItem = plainSelect.getFromItem(); + + // FROM 项是表 + if (fromItem instanceof Table) { + Table table = (Table) fromItem; + this.injectDataPermissionCondition(plainSelect, table, plainSelect.getWhere()); + } + + // FROM是子查询 + if (fromItem instanceof Select) { + PlainSelect subPlainSelect = ((Select) fromItem).getPlainSelect(); + this.enhanceDataPermissionInSelect(subPlainSelect); + } + + // 处理JOIN或关联子查询 + if (plainSelect.getJoins() != null) { + for (Join join : plainSelect.getJoins()) { + if (join.getRightItem() instanceof Select) { + PlainSelect subPlainSelect = ((Select) join.getRightItem()).getPlainSelect(); + this.enhanceDataPermissionInSelect(subPlainSelect); + } + if (join.getRightItem() instanceof Table) { + injectDataPermissionCondition(plainSelect, (Table) join.getRightItem(), plainSelect.getWhere()); + } + } + } + } + + + // 注入数据权限条件 + private void injectDataPermissionCondition(PlainSelect plainSelect, Table table, Expression where) throws Exception { + String tableName = table.getName(); + String aliaName = table.getAlias() != null ? table.getAlias().getName() : tableName; + Condition condition = rowHandler.handler(plainSelect.toString(), tableName, aliaName); + if (condition != null) { + // 添加自定义条件 + Expression customExpression = CCJSqlParserUtil.parseCondExpression(condition.getCondition()); + if (where != null) { + plainSelect.setWhere(new AndExpression(customExpression, where)); + } else { + plainSelect.setWhere(customExpression); + } + } + } + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAlias.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAlias.java new file mode 100644 index 00000000..bd12a457 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAlias.java @@ -0,0 +1,62 @@ +package com.codingapi.springboot.authorization.enhancer; + +import lombok.Getter; + +import java.util.Map; + +/** + * 表字段别名 + */ +public class TableColumnAlias { + + private final String parent; + @Getter + private final String tableName; + @Getter + private final String columnName; + private final String aliasName; + + public TableColumnAlias(String parent, String tableName, String columnName, String aliasName) { + this.parent = parent; + this.tableName = tableName; + this.columnName = columnName; + if (aliasName != null) { + this.aliasName = aliasName + .replaceAll("`", "") + .replaceAll("\"", "") + .replaceAll("'", "") + .trim(); + } else { + this.aliasName = null; + } + } + + /** + * 是否是表 + * + * @param tableAlias 表别名 + * @return 是否是表 + */ + public boolean isTable(Map tableAlias) { + return tableAlias.containsKey(tableName); + } + + + /** + * 获取父级key + * + * @return key + */ + public String getParentKey() { + return parent + "." + aliasName; + } + + /** + * 获取表别名key + * + * @return key + */ + public String getTableAliasKey() { + return tableName + "." + aliasName; + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAliasContext.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAliasContext.java new file mode 100644 index 00000000..f557e2ef --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAliasContext.java @@ -0,0 +1,92 @@ +package com.codingapi.springboot.authorization.enhancer; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 表、字段别名上下文 + */ +public class TableColumnAliasContext { + + private final List columnAliases; + @Getter + private final Map tableAlias; + + private final Map columnAliasMap; + + protected TableColumnAliasContext() { + this.columnAliases = new ArrayList<>(); + this.tableAlias = new HashMap<>(); + this.columnAliasMap = new HashMap<>(); + } + + /** + * 添加表别名 + * @param tableAlias 表别名 + * @param tableName 表名 + */ + protected void addTable(String tableAlias, String tableName) { + this.tableAlias.put(tableAlias, tableName); + } + + /** + * 添加字段别名 + * @param parent 父级(上级别名) + * @param tableName 表名 + * @param columnName 字段名 + * @param aliasName 别名 + */ + protected void addColumn(String parent, String tableName, String columnName, String aliasName) { + TableColumnAlias tableColumnAlias = new TableColumnAlias(parent, tableName, columnName, aliasName); + columnAliases.add(tableColumnAlias); + } + + /** + * 列别名转换为map + */ + protected void columnKeyToMap() { + for (TableColumnAlias tableColumnAlias : columnAliases) { + if (tableColumnAlias.isTable(tableAlias)) { + String parentKey = tableColumnAlias.getParentKey(); + String tableAliasName = tableColumnAlias.getTableName(); + String tableName = this.getTableName(tableAliasName); + String columnValue = tableName + "." + tableColumnAlias.getColumnName(); + columnAliasMap.put(parentKey, columnValue); + columnAliasMap.put(tableColumnAlias.getTableAliasKey(), columnValue); + } + } + } + + /** + * 获取表名(真实表名) + * @param tableName 表名或表别名 + * @return 真实表名 + */ + public String getTableName(String tableName) { + String value = tableAlias.get(tableName); + if (value != null) { + return value; + } + return tableName; + } + + + /** + * 获取字段名(真实字段名) + * @param tableName 表名或表别名 + * @param columnName 字段名 + * @return 真实字段名 + */ + public String getColumnName(String tableName, String columnName) { + String key = tableName + "." + columnName; + String value = columnAliasMap.get(key); + if (value != null) { + return value.split("\\.")[1]; + } + return columnName; + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAliasHolder.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAliasHolder.java new file mode 100644 index 00000000..340c3a4e --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/TableColumnAliasHolder.java @@ -0,0 +1,115 @@ +package com.codingapi.springboot.authorization.enhancer; + +import lombok.Getter; +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.select.*; + +import java.util.List; + +/** + * 表列别名持有者 + */ +public class TableColumnAliasHolder { + + private final Statement statement; + @Getter + private final TableColumnAliasContext aliasContext; + + public TableColumnAliasHolder(Statement statement) { + this.statement = statement; + this.aliasContext = new TableColumnAliasContext(); + } + + + /** + * 获取表列别名 + */ + public void holderAlias() { + Select select = (Select) statement; + PlainSelect plainSelect = select.getPlainSelect(); + this.searchSubSelect(null, plainSelect); + aliasContext.columnKeyToMap(); + } + + + // 增强 SELECT 语句 + private void searchSubSelect(String parent, PlainSelect plainSelect) { + FromItem fromItem = plainSelect.getFromItem(); + + // FROM 项是表 + if (fromItem instanceof Table) { + this.appendTableAlias(fromItem); + Table table = (Table) fromItem; + this.appendColumnAlias(parent, table.getName(), plainSelect.getSelectItems()); + } + + + // FROM是子查询 + if (fromItem instanceof Select) { + PlainSelect subPlainSelect = ((Select) fromItem).getPlainSelect(); + this.appendColumnAlias(parent, null, plainSelect.getSelectItems()); + parent = fromItem.getAlias().getName(); + this.searchSubSelect(parent, subPlainSelect); + } + + // 处理JOIN或关联子查询 + if (plainSelect.getJoins() != null) { + for (Join join : plainSelect.getJoins()) { + if (join.getRightItem() instanceof Select) { + FromItem currentItem = join.getRightItem(); + PlainSelect subPlainSelect = ((Select) currentItem).getPlainSelect(); + this.appendColumnAlias(parent, null, plainSelect.getSelectItems()); + parent = currentItem.getAlias().getName(); + this.searchSubSelect(parent, subPlainSelect); + } + if (join.getRightItem() instanceof Table) { + FromItem currentItem = join.getRightItem(); + this.appendTableAlias(currentItem); + Table table = (Table) currentItem; + this.appendColumnAlias(parent, table.getName(), plainSelect.getSelectItems()); + } + } + } + } + + + /** + * 添加表别名 + * + * @param fromItem 表 + */ + private void appendTableAlias(FromItem fromItem) { + Table table = (Table) fromItem; + Alias alias = table.getAlias(); + String aliasName = alias != null ? alias.getName() : table.getName(); + aliasContext.addTable(aliasName, table.getName()); + } + + + /** + * 添加列别名 + * + * @param parent 父表别名 + * @param selectItems 列 + */ + private void appendColumnAlias(String parent, String tableName, List> selectItems) { + if (selectItems != null) { + for (SelectItem selectItem : selectItems) { + if (selectItem.getExpression() instanceof Column) { + Column column = (Column) selectItem.getExpression(); + if (column.getTable() != null) { + tableName = column.getTable().getName(); + } + String columnName = column.getColumnName(); + Alias columnAlias = selectItem.getAlias(); + String aliasName = columnAlias != null ? selectItem.getAlias().getName() : columnName; + aliasContext.addColumn(parent, tableName, columnName, aliasName); + } + } + } + } + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/exception/NotAuthorizationException.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/exception/NotAuthorizationException.java new file mode 100644 index 00000000..29a7f385 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/exception/NotAuthorizationException.java @@ -0,0 +1,13 @@ +package com.codingapi.springboot.authorization.exception; + +import java.sql.SQLException; + +public class NotAuthorizationException extends SQLException { + + public NotAuthorizationException() { + } + + public NotAuthorizationException(String reason) { + super(reason); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/filter/DataAuthorizationFilter.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/filter/DataAuthorizationFilter.java new file mode 100644 index 00000000..69789928 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/filter/DataAuthorizationFilter.java @@ -0,0 +1,44 @@ +package com.codingapi.springboot.authorization.filter; + +import com.codingapi.springboot.authorization.handler.Condition; + +/** + * 数据权限过滤器 + */ +public interface DataAuthorizationFilter { + + /** + * 列权限过滤 + * @param tableName 表名 + * @param columnName 列名 + * @param value 值 + * @return 过滤后的值 + * @param T + */ + T columnAuthorization(String tableName, String columnName,T value); + + /** + * 行权限过滤 + * @param tableName 表名 + * @param tableAlias 表别名 + * @return 过滤后拦截sql条件 + */ + Condition rowAuthorization(String tableName, String tableAlias); + + /** + * 是否支持列权限过滤 + * @param tableName 表名 + * @param columnName 列名 + * @param value 值 + * @return 是否支持 + */ + boolean supportColumnAuthorization(String tableName, String columnName, Object value); + + /** + * 是否支持行权限过滤 + * @param tableName 表名 + * @param tableAlias 表别名 + * @return 是否支持 + */ + boolean supportRowAuthorization(String tableName, String tableAlias); +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/filter/DefaultDataAuthorizationFilter.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/filter/DefaultDataAuthorizationFilter.java new file mode 100644 index 00000000..ecc26881 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/filter/DefaultDataAuthorizationFilter.java @@ -0,0 +1,27 @@ +package com.codingapi.springboot.authorization.filter; + +import com.codingapi.springboot.authorization.handler.Condition; + +public class DefaultDataAuthorizationFilter implements DataAuthorizationFilter{ + + @Override + public T columnAuthorization(String tableName, String columnName, T value) { + return value; + } + + @Override + public Condition rowAuthorization(String tableName, String tableAlias) { + return null; + } + + @Override + public boolean supportColumnAuthorization(String tableName, String columnName, Object value) { + return false; + } + + @Override + public boolean supportRowAuthorization(String tableName, String tableAlias) { + return false; + } + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/ColumnHandler.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/ColumnHandler.java new file mode 100644 index 00000000..0f1da82a --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/ColumnHandler.java @@ -0,0 +1,74 @@ +package com.codingapi.springboot.authorization.handler; + +import com.codingapi.springboot.authorization.interceptor.SQLInterceptState; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; + +/** + * 列表拦截器 + */ +public interface ColumnHandler { + + String getString(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, String value); + + boolean getBoolean(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, boolean value); + + byte getByte(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, byte value); + + short getShort(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, short value); + + int getInt(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, int value); + + long getLong(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, long value); + + float getFloat(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, float value); + + double getDouble(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, double value); + + BigDecimal getBigDecimal(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, BigDecimal value); + + byte[] getBytes(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, byte[] value); + + Date getDate(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Date value); + + Time getTime(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Time value); + + Timestamp getTimestamp(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Timestamp value); + + InputStream getAsciiStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, InputStream value); + + InputStream getUnicodeStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, InputStream value); + + InputStream getBinaryStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, InputStream value); + + Object getObject(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Object value); + + Reader getCharacterStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Reader value); + + Ref getRef(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Ref value); + + Blob getBlob(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Blob value); + + Clob getClob(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Clob value); + + Array getArray(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Array value); + + URL getURL(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, URL value); + + NClob getNClob(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, NClob value); + + SQLXML getSQLXML(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, SQLXML value); + + String getNString(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, String value); + + Reader getNCharacterStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Reader value); + + RowId getRowId(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, RowId value); + + T getObject(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, T value, Class type); + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/ColumnHandlerContext.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/ColumnHandlerContext.java new file mode 100644 index 00000000..fc0ef6d3 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/ColumnHandlerContext.java @@ -0,0 +1,144 @@ +package com.codingapi.springboot.authorization.handler; + +import com.codingapi.springboot.authorization.interceptor.SQLInterceptState; +import lombok.Getter; +import lombok.Setter; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; + +/** + * ResultSet 拦截器 + */ +@Setter +public class ColumnHandlerContext { + + @Getter + private final static ColumnHandlerContext instance = new ColumnHandlerContext(); + + private ColumnHandlerContext() { + this.columnHandler = new DefaultColumnHandler(); + } + + private ColumnHandler columnHandler; + + + public String getString(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, String value) { + return columnHandler.getString(interceptState, columnIndex, tableName, columnName, value); + } + + public short getShort(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, short value) { + return columnHandler.getShort(interceptState, columnIndex, tableName, columnName, value); + } + + public boolean getBoolean(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, boolean value) { + return columnHandler.getBoolean(interceptState, columnIndex, tableName, columnName, value); + } + + public byte getByte(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, byte value) { + return columnHandler.getByte(interceptState, columnIndex, tableName, columnName, value); + } + + public int getInt(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, int value) { + return columnHandler.getInt(interceptState, columnIndex, tableName, columnName, value); + } + + public long getLong(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, long value) { + return columnHandler.getLong(interceptState, columnIndex, tableName, columnName, value); + } + + public float getFloat(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, float value) { + return columnHandler.getFloat(interceptState, columnIndex, tableName, columnName, value); + } + + public double getDouble(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, double value) { + return columnHandler.getDouble(interceptState, columnIndex, tableName, columnName, value); + } + + public BigDecimal getBigDecimal(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, BigDecimal value) { + return columnHandler.getBigDecimal(interceptState, columnIndex, tableName, columnName, value); + } + + public byte[] getBytes(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, byte[] value) { + return columnHandler.getBytes(interceptState, columnIndex, tableName, columnName, value); + } + + public Timestamp getTimestamp(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Timestamp value) { + return columnHandler.getTimestamp(interceptState, columnIndex, tableName, columnName, value); + } + + public Time getTime(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Time value) { + return columnHandler.getTime(interceptState, columnIndex, tableName, columnName, value); + } + + public Date getDate(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Date value) { + return columnHandler.getDate(interceptState, columnIndex, tableName, columnName, value); + } + + public InputStream getAsciiStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, InputStream value) { + return columnHandler.getAsciiStream(interceptState, columnIndex, tableName, columnName, value); + } + + public InputStream getUnicodeStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, InputStream value) { + return columnHandler.getUnicodeStream(interceptState, columnIndex, tableName, columnName, value); + } + + public InputStream getBinaryStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, InputStream value) { + return columnHandler.getBinaryStream(interceptState, columnIndex, tableName, columnName, value); + } + + public Object getObject(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Object value) { + return columnHandler.getObject(interceptState, columnIndex, tableName, columnName, value); + } + + public Reader getCharacterStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Reader value) { + return columnHandler.getCharacterStream(interceptState, columnIndex, tableName, columnName, value); + } + + public Ref getRef(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Ref value) { + return columnHandler.getRef(interceptState, columnIndex, tableName, columnName, value); + } + + public Blob getBlob(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Blob value) { + return columnHandler.getBlob(interceptState, columnIndex, tableName, columnName, value); + } + + public Clob getClob(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Clob value) { + return columnHandler.getClob(interceptState, columnIndex, tableName, columnName, value); + } + + public Array getArray(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Array value) { + return columnHandler.getArray(interceptState, columnIndex, tableName, columnName, value); + } + + public URL getURL(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, URL value) { + return columnHandler.getURL(interceptState, columnIndex, tableName, columnName, value); + } + + public NClob getNClob(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, NClob value) { + return columnHandler.getNClob(interceptState, columnIndex, tableName, columnName, value); + } + + public SQLXML getSQLXML(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, SQLXML value) { + return columnHandler.getSQLXML(interceptState, columnIndex, tableName, columnName, value); + } + + public String getNString(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, String value) { + return columnHandler.getNString(interceptState, columnIndex, tableName, columnName, value); + } + + public Reader getNCharacterStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Reader value) { + return columnHandler.getNCharacterStream(interceptState, columnIndex, tableName, columnName, value); + } + + public RowId getRowId(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, RowId value) { + return columnHandler.getRowId(interceptState, columnIndex, tableName, columnName, value); + } + + public T getObject(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, T value, Class type) { + return columnHandler.getObject(interceptState, columnIndex, tableName, columnName, value, type); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/Condition.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/Condition.java new file mode 100644 index 00000000..3cb6d62e --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/Condition.java @@ -0,0 +1,33 @@ +package com.codingapi.springboot.authorization.handler; + +import lombok.Getter; + +/** + * 查询条件 + */ +@Getter +public class Condition { + + private final String condition; + + private Condition(String condition) { + this.condition = condition; + } + + public static Condition customCondition(String condition) { + return new Condition(condition); + } + + public static Condition formatCondition(String condition, Object... args) { + return new Condition(String.format(condition, args)); + } + + public static Condition emptyCondition() { + return null; + } + + public static Condition defaultCondition() { + return new Condition("1=1"); + } + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/DefaultColumnHandler.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/DefaultColumnHandler.java new file mode 100644 index 00000000..ff60b751 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/DefaultColumnHandler.java @@ -0,0 +1,161 @@ +package com.codingapi.springboot.authorization.handler; + +import com.codingapi.springboot.authorization.DataAuthorizationContext; +import com.codingapi.springboot.authorization.interceptor.SQLInterceptState; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; + +/** + * 默认ResultSet 拦截器 + */ +public class DefaultColumnHandler implements ColumnHandler { + + @Override + public String getString(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, String value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public boolean getBoolean(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, boolean value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public byte getByte(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, byte value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public short getShort(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, short value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public int getInt(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, int value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public long getLong(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, long value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public float getFloat(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, float value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public double getDouble(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, double value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public BigDecimal getBigDecimal(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, BigDecimal value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public byte[] getBytes(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, byte[] value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public Date getDate(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Date value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public Time getTime(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Time value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public Timestamp getTimestamp(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Timestamp value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public InputStream getAsciiStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, InputStream value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public InputStream getUnicodeStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, InputStream value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public InputStream getBinaryStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, InputStream value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public Object getObject(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Object value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public Reader getCharacterStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Reader value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public Ref getRef(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Ref value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public Blob getBlob(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Blob value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public Clob getClob(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Clob value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public Array getArray(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Array value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public URL getURL(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, URL value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public NClob getNClob(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, NClob value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public SQLXML getSQLXML(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, SQLXML value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public String getNString(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, String value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public Reader getNCharacterStream(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, Reader value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public RowId getRowId(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, RowId value) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } + + @Override + public T getObject(SQLInterceptState interceptState, int columnIndex, String tableName, String columnName, T value, Class type) { + return DataAuthorizationContext.getInstance().columnAuthorization(interceptState,tableName, columnName, value); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/DefaultRowHandler.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/DefaultRowHandler.java new file mode 100644 index 00000000..972075cf --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/DefaultRowHandler.java @@ -0,0 +1,11 @@ +package com.codingapi.springboot.authorization.handler; + +import com.codingapi.springboot.authorization.DataAuthorizationContext; + +public class DefaultRowHandler implements RowHandler { + + @Override + public Condition handler(String subSql, String tableName, String tableAlias) { + return DataAuthorizationContext.getInstance().rowAuthorization(tableName, tableAlias); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/RowHandler.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/RowHandler.java new file mode 100644 index 00000000..7262d5c4 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/RowHandler.java @@ -0,0 +1,19 @@ +package com.codingapi.springboot.authorization.handler; + +/** + * 行数据权限处理器 + */ +public interface RowHandler { + + /** + * 查询条件拦截 + * + * @param subSql 查询子SQL语句 + * @param tableName 表名 + * @param tableAlias 表别名 + * @return 条件语句 + */ + Condition handler(String subSql, String tableName, String tableAlias); + + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/RowHandlerContext.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/RowHandlerContext.java new file mode 100644 index 00000000..5d096177 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/handler/RowHandlerContext.java @@ -0,0 +1,18 @@ +package com.codingapi.springboot.authorization.handler; + +import lombok.Getter; +import lombok.Setter; + +@Setter +public class RowHandlerContext { + + @Getter + private final static RowHandlerContext instance = new RowHandlerContext(); + + @Getter + private RowHandler rowHandler; + + private RowHandlerContext() { + this.rowHandler = new DefaultRowHandler(); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DataPermissionSQL.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DataPermissionSQL.java new file mode 100644 index 00000000..b0b47df8 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DataPermissionSQL.java @@ -0,0 +1,18 @@ +package com.codingapi.springboot.authorization.interceptor; + +import com.codingapi.springboot.authorization.enhancer.TableColumnAliasContext; +import lombok.Getter; + +@Getter +public class DataPermissionSQL { + + private final String sql; + private final String newSql; + private final TableColumnAliasContext aliasContext; + + public DataPermissionSQL(String sql, String newSql, TableColumnAliasContext aliasContext) { + this.sql = sql; + this.newSql = newSql; + this.aliasContext = aliasContext; + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DefaultSQLInterceptor.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DefaultSQLInterceptor.java new file mode 100644 index 00000000..8d658633 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DefaultSQLInterceptor.java @@ -0,0 +1,35 @@ +package com.codingapi.springboot.authorization.interceptor; + + +import com.codingapi.springboot.authorization.enhancer.DataPermissionSQLEnhancer; +import com.codingapi.springboot.authorization.handler.RowHandler; +import com.codingapi.springboot.authorization.handler.RowHandlerContext; +import com.codingapi.springboot.authorization.properties.DataAuthorizationPropertyContext; +import com.codingapi.springboot.authorization.utils.SQLUtils; +import lombok.extern.slf4j.Slf4j; + +import java.sql.SQLException; + +@Slf4j +public class DefaultSQLInterceptor implements SQLInterceptor { + + @Override + public boolean beforeHandler(String sql) { + return SQLUtils.isQuerySql(sql); + } + + + @Override + public void afterHandler(String sql, String newSql, SQLException exception) { + if (DataAuthorizationPropertyContext.getInstance().showSql()) { + log.info("newSql:{}", newSql); + } + } + + @Override + public DataPermissionSQL postHandler(String sql) throws SQLException { + RowHandler rowHandler = RowHandlerContext.getInstance().getRowHandler(); + DataPermissionSQLEnhancer sqlEnhancer = new DataPermissionSQLEnhancer(sql, rowHandler); + return new DataPermissionSQL(sql, sqlEnhancer.getNewSQL(), sqlEnhancer.getTableAlias()); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptState.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptState.java new file mode 100644 index 00000000..809668fb --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptState.java @@ -0,0 +1,60 @@ +package com.codingapi.springboot.authorization.interceptor; + +import com.codingapi.springboot.authorization.enhancer.TableColumnAliasContext; + +/** + * SQL拦截状态 + */ +public class SQLInterceptState { + + private final boolean state; + + private final String sql; + + private final String newSql; + + private final TableColumnAliasContext aliasContext; + + private SQLInterceptState(boolean state, String sql, String newSql, TableColumnAliasContext aliasContext) { + this.state = state; + this.sql = sql; + this.newSql = newSql; + this.aliasContext = aliasContext; + } + + /** + * 拦截 + */ + public static SQLInterceptState intercept(String sql, String newSql, TableColumnAliasContext aliasContext) { + return new SQLInterceptState(true, sql, newSql, aliasContext); + } + + /** + * 不拦截 + */ + public static SQLInterceptState unIntercept(String sql) { + return new SQLInterceptState(false, sql, sql, null); + } + + public String getTableName(String tableName) { + return aliasContext.getTableName(tableName); + } + + public String getColumnName(String tableName, String columnName) { + return aliasContext.getColumnName(tableName, columnName); + } + + public String getSql() { + if (state) { + return newSql; + } else { + return sql; + } + } + + public boolean hasIntercept() { + return state; + } + + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptor.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptor.java new file mode 100644 index 00000000..dd627f5d --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptor.java @@ -0,0 +1,39 @@ +package com.codingapi.springboot.authorization.interceptor; + +import java.sql.SQLException; + +/** + * SQL查询条件处理器 + */ +public interface SQLInterceptor { + + + /** + * 前置处理 + * + * @param sql sql + * @return 是否处理 + */ + boolean beforeHandler(String sql); + + + /** + * 处理sql + * + * @param sql sql + * @return 处理后的sql newSql + * @throws SQLException + */ + DataPermissionSQL postHandler(String sql) throws SQLException; + + + /** + * 后置处理 + * @param sql sql + * @param newSql newSql + * @param exception exception + */ + void afterHandler(String sql, String newSql, SQLException exception); + + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptorContext.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptorContext.java new file mode 100644 index 00000000..178de534 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLInterceptorContext.java @@ -0,0 +1,20 @@ +package com.codingapi.springboot.authorization.interceptor; + +import lombok.Getter; +import lombok.Setter; + +@Setter +public class SQLInterceptorContext { + + @Getter + private final static SQLInterceptorContext instance = new SQLInterceptorContext(); + + @Getter + private SQLInterceptor sqlInterceptor; + + private SQLInterceptorContext() { + this.sqlInterceptor = new DefaultSQLInterceptor(); + } + + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLRunningContext.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLRunningContext.java new file mode 100644 index 00000000..fab68f60 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLRunningContext.java @@ -0,0 +1,67 @@ +package com.codingapi.springboot.authorization.interceptor; + +import lombok.Getter; + +import java.sql.SQLException; + +/** + * SQLRunningContext SQL执行拦截上下文 + */ +public class SQLRunningContext { + + @Getter + private final static SQLRunningContext instance = new SQLRunningContext(); + + private final ThreadLocal skipInterceptor = ThreadLocal.withInitial(() -> false); + + private SQLRunningContext() { + } + + /** + * 拦截SQL + * + * @param sql sql + * @return SQLInterceptState + * @throws SQLException SQLException + */ + public SQLInterceptState intercept(String sql) throws SQLException { + SQLInterceptor sqlInterceptor = SQLInterceptorContext.getInstance().getSqlInterceptor(); + + if (skipInterceptor.get()) { + return SQLInterceptState.unIntercept(sql); + } + try { + if (sqlInterceptor.beforeHandler(sql)) { + // 在拦截器中执行的查询操作将不会被拦截 + skipInterceptor.set(true); + DataPermissionSQL dataPermissionSQL = sqlInterceptor.postHandler(sql); + sqlInterceptor.afterHandler(sql, dataPermissionSQL.getNewSql(), null); + return SQLInterceptState.intercept(sql, dataPermissionSQL.getNewSql(), dataPermissionSQL.getAliasContext()); + } + } catch (SQLException exception) { + sqlInterceptor.afterHandler(sql, null, exception); + } finally { + // 重置拦截器状态 + skipInterceptor.set(false); + } + return SQLInterceptState.unIntercept(sql); + } + + + /** + * 跳过数据权限拦截 + * + * @param supplier 业务逻辑 + * @param T + * @return T + */ + public T skipDataAuthorization(java.util.function.Supplier supplier) { + try { + skipInterceptor.set(true); + return (T) supplier.get(); + } finally { + skipInterceptor.set(false); + } + } + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java new file mode 100644 index 00000000..93045795 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java @@ -0,0 +1,57 @@ +package com.codingapi.springboot.authorization.jdbc; + + +import com.codingapi.springboot.authorization.jdbc.proxy.ConnectionProxy; + +import java.sql.*; +import java.util.Enumeration; +import java.util.Properties; +import java.util.logging.Logger; + +public class AuthorizationJdbcDriver implements Driver { + + private Driver driver; + + @Override + public Connection connect(String url, Properties info) throws SQLException { + return new ConnectionProxy(driver.connect(url, info)); + } + + @Override + public boolean acceptsURL(String url) throws SQLException { + Enumeration drivers = DriverManager.getDrivers(); + while (drivers.hasMoreElements()) { + Driver driver = drivers.nextElement(); + if (driver.acceptsURL(url)) { + this.driver = driver; + return true; + } + } + return false; + } + + @Override + public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { + return driver.getPropertyInfo(url, info); + } + + @Override + public int getMajorVersion() { + return driver.getMajorVersion(); + } + + @Override + public int getMinorVersion() { + return driver.getMinorVersion(); + } + + @Override + public boolean jdbcCompliant() { + return driver.jdbcCompliant(); + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + return driver.getParentLogger(); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/CallableStatementProxy.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/CallableStatementProxy.java new file mode 100644 index 00000000..8f2b77b7 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/CallableStatementProxy.java @@ -0,0 +1,1191 @@ +package com.codingapi.springboot.authorization.jdbc.proxy; + +import com.codingapi.springboot.authorization.interceptor.SQLInterceptState; +import com.codingapi.springboot.authorization.interceptor.SQLRunningContext; +import lombok.AllArgsConstructor; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; +import java.util.Calendar; +import java.util.Map; + +@AllArgsConstructor +public class CallableStatementProxy implements CallableStatement { + + private final CallableStatement callableStatement; + + private SQLInterceptState interceptState; + + @Override + public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException { + callableStatement.registerOutParameter(parameterIndex, sqlType); + } + + @Override + public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException { + callableStatement.registerOutParameter(parameterIndex, sqlType, scale); + } + + @Override + public boolean wasNull() throws SQLException { + return callableStatement.wasNull(); + } + + @Override + public String getString(int parameterIndex) throws SQLException { + return callableStatement.getString(parameterIndex); + } + + @Override + public boolean getBoolean(int parameterIndex) throws SQLException { + return callableStatement.getBoolean(parameterIndex); + } + + @Override + public byte getByte(int parameterIndex) throws SQLException { + return callableStatement.getByte(parameterIndex); + } + + @Override + public short getShort(int parameterIndex) throws SQLException { + return callableStatement.getShort(parameterIndex); + } + + @Override + public int getInt(int parameterIndex) throws SQLException { + return callableStatement.getInt(parameterIndex); + } + + @Override + public long getLong(int parameterIndex) throws SQLException { + return callableStatement.getLong(parameterIndex); + } + + @Override + public float getFloat(int parameterIndex) throws SQLException { + return callableStatement.getFloat(parameterIndex); + } + + @Override + public double getDouble(int parameterIndex) throws SQLException { + return callableStatement.getDouble(parameterIndex); + } + + @Override + public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException { + return callableStatement.getBigDecimal(parameterIndex, scale); + } + + @Override + public byte[] getBytes(int parameterIndex) throws SQLException { + return callableStatement.getBytes(parameterIndex); + } + + @Override + public Date getDate(int parameterIndex) throws SQLException { + return callableStatement.getDate(parameterIndex); + } + + @Override + public Time getTime(int parameterIndex) throws SQLException { + return callableStatement.getTime(parameterIndex); + } + + @Override + public Timestamp getTimestamp(int parameterIndex) throws SQLException { + return callableStatement.getTimestamp(parameterIndex); + } + + @Override + public Object getObject(int parameterIndex) throws SQLException { + return callableStatement.getObject(parameterIndex); + } + + @Override + public BigDecimal getBigDecimal(int parameterIndex) throws SQLException { + return callableStatement.getBigDecimal(parameterIndex); + } + + @Override + public Object getObject(int parameterIndex, Map> map) throws SQLException { + return callableStatement.getObject(parameterIndex, map); + } + + @Override + public Ref getRef(int parameterIndex) throws SQLException { + return callableStatement.getRef(parameterIndex); + } + + @Override + public Blob getBlob(int parameterIndex) throws SQLException { + return callableStatement.getBlob(parameterIndex); + } + + @Override + public Clob getClob(int parameterIndex) throws SQLException { + return callableStatement.getClob(parameterIndex); + } + + @Override + public Array getArray(int parameterIndex) throws SQLException { + return callableStatement.getArray(parameterIndex); + } + + @Override + public Date getDate(int parameterIndex, Calendar cal) throws SQLException { + return callableStatement.getDate(parameterIndex, cal); + } + + @Override + public Time getTime(int parameterIndex, Calendar cal) throws SQLException { + return callableStatement.getTime(parameterIndex, cal); + } + + @Override + public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException { + return callableStatement.getTimestamp(parameterIndex, cal); + } + + @Override + public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException { + callableStatement.registerOutParameter(parameterIndex, sqlType, typeName); + } + + @Override + public void registerOutParameter(String parameterName, int sqlType) throws SQLException { + callableStatement.registerOutParameter(parameterName, sqlType); + } + + @Override + public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException { + callableStatement.registerOutParameter(parameterName, sqlType, scale); + } + + @Override + public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException { + callableStatement.registerOutParameter(parameterName, sqlType, typeName); + } + + @Override + public URL getURL(int parameterIndex) throws SQLException { + return callableStatement.getURL(parameterIndex); + } + + @Override + public void setURL(String parameterName, URL val) throws SQLException { + callableStatement.setURL(parameterName, val); + } + + @Override + public void setNull(String parameterName, int sqlType) throws SQLException { + callableStatement.setNull(parameterName, sqlType); + } + + @Override + public void setBoolean(String parameterName, boolean x) throws SQLException { + callableStatement.setBoolean(parameterName, x); + } + + @Override + public void setByte(String parameterName, byte x) throws SQLException { + callableStatement.setByte(parameterName, x); + } + + @Override + public void setShort(String parameterName, short x) throws SQLException { + callableStatement.setShort(parameterName, x); + } + + @Override + public void setInt(String parameterName, int x) throws SQLException { + callableStatement.setInt(parameterName, x); + } + + @Override + public void setLong(String parameterName, long x) throws SQLException { + callableStatement.setLong(parameterName, x); + } + + @Override + public void setFloat(String parameterName, float x) throws SQLException { + callableStatement.setFloat(parameterName, x); + } + + @Override + public void setDouble(String parameterName, double x) throws SQLException { + callableStatement.setDouble(parameterName, x); + } + + @Override + public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException { + callableStatement.setBigDecimal(parameterName, x); + } + + @Override + public void setString(String parameterName, String x) throws SQLException { + callableStatement.setString(parameterName, x); + } + + @Override + public void setBytes(String parameterName, byte[] x) throws SQLException { + callableStatement.setBytes(parameterName, x); + } + + @Override + public void setDate(String parameterName, Date x) throws SQLException { + callableStatement.setDate(parameterName, x); + } + + @Override + public void setTime(String parameterName, Time x) throws SQLException { + callableStatement.setTime(parameterName, x); + } + + @Override + public void setTimestamp(String parameterName, Timestamp x) throws SQLException { + callableStatement.setTimestamp(parameterName, x); + } + + @Override + public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException { + callableStatement.setAsciiStream(parameterName, x, length); + } + + @Override + public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException { + callableStatement.setBinaryStream(parameterName, x, length); + } + + @Override + public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException { + callableStatement.setObject(parameterName, x, targetSqlType, scale); + } + + @Override + public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException { + callableStatement.setObject(parameterName, x, targetSqlType); + } + + @Override + public void setObject(String parameterName, Object x) throws SQLException { + callableStatement.setObject(parameterName, x); + } + + @Override + public void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException { + callableStatement.setCharacterStream(parameterName, reader, length); + } + + @Override + public void setDate(String parameterName, Date x, Calendar cal) throws SQLException { + callableStatement.setDate(parameterName, x, cal); + } + + @Override + public void setTime(String parameterName, Time x, Calendar cal) throws SQLException { + callableStatement.setTime(parameterName, x, cal); + } + + @Override + public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException { + callableStatement.setTimestamp(parameterName, x, cal); + } + + @Override + public void setNull(String parameterName, int sqlType, String typeName) throws SQLException { + callableStatement.setNull(parameterName, sqlType, typeName); + } + + @Override + public String getString(String parameterName) throws SQLException { + return callableStatement.getString(parameterName); + } + + @Override + public boolean getBoolean(String parameterName) throws SQLException { + return callableStatement.getBoolean(parameterName); + } + + @Override + public byte getByte(String parameterName) throws SQLException { + return callableStatement.getByte(parameterName); + } + + @Override + public short getShort(String parameterName) throws SQLException { + return callableStatement.getShort(parameterName); + } + + @Override + public int getInt(String parameterName) throws SQLException { + return callableStatement.getInt(parameterName); + } + + @Override + public long getLong(String parameterName) throws SQLException { + return callableStatement.getLong(parameterName); + } + + @Override + public float getFloat(String parameterName) throws SQLException { + return callableStatement.getFloat(parameterName); + } + + @Override + public double getDouble(String parameterName) throws SQLException { + return callableStatement.getDouble(parameterName); + } + + @Override + public byte[] getBytes(String parameterName) throws SQLException { + return callableStatement.getBytes(parameterName); + } + + @Override + public Date getDate(String parameterName) throws SQLException { + return callableStatement.getDate(parameterName); + } + + @Override + public Time getTime(String parameterName) throws SQLException { + return callableStatement.getTime(parameterName); + } + + @Override + public Timestamp getTimestamp(String parameterName) throws SQLException { + return callableStatement.getTimestamp(parameterName); + } + + @Override + public Object getObject(String parameterName) throws SQLException { + return callableStatement.getObject(parameterName); + } + + @Override + public BigDecimal getBigDecimal(String parameterName) throws SQLException { + return callableStatement.getBigDecimal(parameterName); + } + + @Override + public Object getObject(String parameterName, Map> map) throws SQLException { + return callableStatement.getObject(parameterName, map); + } + + @Override + public Ref getRef(String parameterName) throws SQLException { + return callableStatement.getRef(parameterName); + } + + @Override + public Blob getBlob(String parameterName) throws SQLException { + return callableStatement.getBlob(parameterName); + } + + @Override + public Clob getClob(String parameterName) throws SQLException { + return callableStatement.getClob(parameterName); + } + + @Override + public Array getArray(String parameterName) throws SQLException { + return callableStatement.getArray(parameterName); + } + + @Override + public Date getDate(String parameterName, Calendar cal) throws SQLException { + return callableStatement.getDate(parameterName, cal); + } + + @Override + public Time getTime(String parameterName, Calendar cal) throws SQLException { + return callableStatement.getTime(parameterName, cal); + } + + @Override + public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException { + return callableStatement.getTimestamp(parameterName, cal); + } + + @Override + public URL getURL(String parameterName) throws SQLException { + return callableStatement.getURL(parameterName); + } + + @Override + public RowId getRowId(int parameterIndex) throws SQLException { + return callableStatement.getRowId(parameterIndex); + } + + @Override + public RowId getRowId(String parameterName) throws SQLException { + return callableStatement.getRowId(parameterName); + } + + @Override + public void setRowId(String parameterName, RowId x) throws SQLException { + callableStatement.setRowId(parameterName, x); + } + + @Override + public void setNString(String parameterName, String value) throws SQLException { + callableStatement.setNString(parameterName, value); + } + + @Override + public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException { + callableStatement.setNCharacterStream(parameterName, value, length); + } + + @Override + public void setNClob(String parameterName, NClob value) throws SQLException { + callableStatement.setNClob(parameterName, value); + } + + @Override + public void setClob(String parameterName, Reader reader, long length) throws SQLException { + callableStatement.setClob(parameterName, reader, length); + } + + @Override + public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException { + callableStatement.setBlob(parameterName, inputStream, length); + } + + @Override + public void setNClob(String parameterName, Reader reader, long length) throws SQLException { + callableStatement.setNClob(parameterName, reader, length); + } + + @Override + public NClob getNClob(int parameterIndex) throws SQLException { + return callableStatement.getNClob(parameterIndex); + } + + @Override + public NClob getNClob(String parameterName) throws SQLException { + return callableStatement.getNClob(parameterName); + } + + @Override + public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException { + callableStatement.setSQLXML(parameterName, xmlObject); + } + + @Override + public SQLXML getSQLXML(int parameterIndex) throws SQLException { + return callableStatement.getSQLXML(parameterIndex); + } + + @Override + public SQLXML getSQLXML(String parameterName) throws SQLException { + return callableStatement.getSQLXML(parameterName); + } + + @Override + public String getNString(int parameterIndex) throws SQLException { + return callableStatement.getNString(parameterIndex); + } + + @Override + public String getNString(String parameterName) throws SQLException { + return callableStatement.getNString(parameterName); + } + + @Override + public Reader getNCharacterStream(int parameterIndex) throws SQLException { + return callableStatement.getNCharacterStream(parameterIndex); + } + + @Override + public Reader getNCharacterStream(String parameterName) throws SQLException { + return callableStatement.getNCharacterStream(parameterName); + } + + @Override + public Reader getCharacterStream(int parameterIndex) throws SQLException { + return callableStatement.getCharacterStream(parameterIndex); + } + + @Override + public Reader getCharacterStream(String parameterName) throws SQLException { + return callableStatement.getCharacterStream(parameterName); + } + + @Override + public void setBlob(String parameterName, Blob x) throws SQLException { + callableStatement.setBlob(parameterName, x); + } + + @Override + public void setClob(String parameterName, Clob x) throws SQLException { + callableStatement.setClob(parameterName, x); + } + + @Override + public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException { + callableStatement.setAsciiStream(parameterName, x, length); + } + + @Override + public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException { + callableStatement.setBinaryStream(parameterName, x, length); + } + + @Override + public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException { + callableStatement.setCharacterStream(parameterName, reader, length); + } + + @Override + public void setAsciiStream(String parameterName, InputStream x) throws SQLException { + callableStatement.setAsciiStream(parameterName, x); + } + + @Override + public void setBinaryStream(String parameterName, InputStream x) throws SQLException { + callableStatement.setBinaryStream(parameterName, x); + } + + @Override + public void setCharacterStream(String parameterName, Reader reader) throws SQLException { + callableStatement.setCharacterStream(parameterName, reader); + } + + @Override + public void setNCharacterStream(String parameterName, Reader value) throws SQLException { + callableStatement.setNCharacterStream(parameterName, value); + } + + @Override + public void setClob(String parameterName, Reader reader) throws SQLException { + callableStatement.setClob(parameterName, reader); + } + + @Override + public void setBlob(String parameterName, InputStream inputStream) throws SQLException { + callableStatement.setBlob(parameterName, inputStream); + } + + @Override + public void setNClob(String parameterName, Reader reader) throws SQLException { + callableStatement.setNClob(parameterName, reader); + } + + @Override + public T getObject(int parameterIndex, Class type) throws SQLException { + return callableStatement.getObject(parameterIndex, type); + } + + @Override + public T getObject(String parameterName, Class type) throws SQLException { + return callableStatement.getObject(parameterName, type); + } + + @Override + public void setObject(String parameterName, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException { + callableStatement.setObject(parameterName, x, targetSqlType, scaleOrLength); + } + + @Override + public void setObject(String parameterName, Object x, SQLType targetSqlType) throws SQLException { + callableStatement.setObject(parameterName, x, targetSqlType); + } + + @Override + public void registerOutParameter(int parameterIndex, SQLType sqlType) throws SQLException { + callableStatement.registerOutParameter(parameterIndex, sqlType); + } + + @Override + public void registerOutParameter(int parameterIndex, SQLType sqlType, int scale) throws SQLException { + callableStatement.registerOutParameter(parameterIndex, sqlType, scale); + } + + @Override + public void registerOutParameter(int parameterIndex, SQLType sqlType, String typeName) throws SQLException { + callableStatement.registerOutParameter(parameterIndex, sqlType, typeName); + } + + @Override + public void registerOutParameter(String parameterName, SQLType sqlType) throws SQLException { + callableStatement.registerOutParameter(parameterName, sqlType); + } + + @Override + public void registerOutParameter(String parameterName, SQLType sqlType, int scale) throws SQLException { + callableStatement.registerOutParameter(parameterName, sqlType, scale); + } + + @Override + public void registerOutParameter(String parameterName, SQLType sqlType, String typeName) throws SQLException { + callableStatement.registerOutParameter(parameterName, sqlType, typeName); + } + + @Override + public ResultSet executeQuery() throws SQLException { + return new ResultSetProxy(callableStatement.executeQuery(),this.interceptState); + } + + @Override + public int executeUpdate() throws SQLException { + return callableStatement.executeUpdate(); + } + + @Override + public void setNull(int parameterIndex, int sqlType) throws SQLException { + callableStatement.setNull(parameterIndex, sqlType); + } + + @Override + public void setBoolean(int parameterIndex, boolean x) throws SQLException { + callableStatement.setBoolean(parameterIndex, x); + } + + @Override + public void setByte(int parameterIndex, byte x) throws SQLException { + callableStatement.setByte(parameterIndex, x); + } + + @Override + public void setShort(int parameterIndex, short x) throws SQLException { + callableStatement.setShort(parameterIndex, x); + } + + @Override + public void setInt(int parameterIndex, int x) throws SQLException { + callableStatement.setInt(parameterIndex, x); + } + + @Override + public void setLong(int parameterIndex, long x) throws SQLException { + callableStatement.setLong(parameterIndex, x); + } + + @Override + public void setFloat(int parameterIndex, float x) throws SQLException { + callableStatement.setFloat(parameterIndex, x); + } + + @Override + public void setDouble(int parameterIndex, double x) throws SQLException { + callableStatement.setDouble(parameterIndex, x); + } + + @Override + public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { + callableStatement.setBigDecimal(parameterIndex, x); + } + + @Override + public void setString(int parameterIndex, String x) throws SQLException { + callableStatement.setString(parameterIndex, x); + } + + @Override + public void setBytes(int parameterIndex, byte[] x) throws SQLException { + callableStatement.setBytes(parameterIndex, x); + } + + @Override + public void setDate(int parameterIndex, Date x) throws SQLException { + callableStatement.setDate(parameterIndex, x); + } + + @Override + public void setTime(int parameterIndex, Time x) throws SQLException { + callableStatement.setTime(parameterIndex, x); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { + callableStatement.setTimestamp(parameterIndex, x); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { + callableStatement.setAsciiStream(parameterIndex, x, length); + } + + @Override + public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { + callableStatement.setUnicodeStream(parameterIndex, x, length); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { + callableStatement.setBinaryStream(parameterIndex, x, length); + } + + @Override + public void clearParameters() throws SQLException { + callableStatement.clearParameters(); + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { + callableStatement.setObject(parameterIndex, x, targetSqlType); + } + + @Override + public void setObject(int parameterIndex, Object x) throws SQLException { + callableStatement.setObject(parameterIndex, x); + } + + @Override + public boolean execute() throws SQLException { + return callableStatement.execute(); + } + + @Override + public void addBatch() throws SQLException { + callableStatement.addBatch(); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { + callableStatement.setCharacterStream(parameterIndex, reader, length); + } + + @Override + public void setRef(int parameterIndex, Ref x) throws SQLException { + callableStatement.setRef(parameterIndex, x); + } + + @Override + public void setBlob(int parameterIndex, Blob x) throws SQLException { + callableStatement.setBlob(parameterIndex, x); + } + + @Override + public void setClob(int parameterIndex, Clob x) throws SQLException { + callableStatement.setClob(parameterIndex, x); + } + + @Override + public void setArray(int parameterIndex, Array x) throws SQLException { + callableStatement.setArray(parameterIndex, x); + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return callableStatement.getMetaData(); + } + + @Override + public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { + callableStatement.setDate(parameterIndex, x, cal); + } + + @Override + public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { + callableStatement.setTime(parameterIndex, x, cal); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { + callableStatement.setTimestamp(parameterIndex, x, cal); + } + + @Override + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { + callableStatement.setNull(parameterIndex, sqlType, typeName); + } + + @Override + public void setURL(int parameterIndex, URL x) throws SQLException { + callableStatement.setURL(parameterIndex, x); + } + + @Override + public ParameterMetaData getParameterMetaData() throws SQLException { + return callableStatement.getParameterMetaData(); + } + + @Override + public void setRowId(int parameterIndex, RowId x) throws SQLException { + callableStatement.setRowId(parameterIndex, x); + } + + @Override + public void setNString(int parameterIndex, String value) throws SQLException { + callableStatement.setNString(parameterIndex, value); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { + callableStatement.setNCharacterStream(parameterIndex, value, length); + } + + @Override + public void setNClob(int parameterIndex, NClob value) throws SQLException { + callableStatement.setNClob(parameterIndex, value); + } + + @Override + public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { + callableStatement.setClob(parameterIndex, reader, length); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { + callableStatement.setBlob(parameterIndex, inputStream, length); + } + + @Override + public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { + callableStatement.setNClob(parameterIndex, reader, length); + } + + @Override + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + callableStatement.setSQLXML(parameterIndex, xmlObject); + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { + callableStatement.setObject(parameterIndex, x, targetSqlType, scaleOrLength); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + callableStatement.setAsciiStream(parameterIndex, x, length); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + callableStatement.setBinaryStream(parameterIndex, x, length); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { + callableStatement.setCharacterStream(parameterIndex, reader, length); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + callableStatement.setAsciiStream(parameterIndex, x); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + callableStatement.setBinaryStream(parameterIndex, x); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + callableStatement.setCharacterStream(parameterIndex, reader); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + callableStatement.setNCharacterStream(parameterIndex, value); + } + + @Override + public void setClob(int parameterIndex, Reader reader) throws SQLException { + callableStatement.setClob(parameterIndex, reader); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { + callableStatement.setBlob(parameterIndex, inputStream); + } + + @Override + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + callableStatement.setNClob(parameterIndex, reader); + } + + @Override + public void setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException { + callableStatement.setObject(parameterIndex, x, targetSqlType, scaleOrLength); + } + + @Override + public void setObject(int parameterIndex, Object x, SQLType targetSqlType) throws SQLException { + callableStatement.setObject(parameterIndex, x, targetSqlType); + } + + @Override + public long executeLargeUpdate() throws SQLException { + return callableStatement.executeLargeUpdate(); + } + + @Override + public ResultSet executeQuery(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new ResultSetProxy(callableStatement.executeQuery(interceptState.getSql()),this.interceptState); + } + + @Override + public int executeUpdate(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.executeUpdate(interceptState.getSql()); + } + + @Override + public void close() throws SQLException { + callableStatement.close(); + } + + @Override + public int getMaxFieldSize() throws SQLException { + return callableStatement.getMaxFieldSize(); + } + + @Override + public void setMaxFieldSize(int max) throws SQLException { + callableStatement.setMaxFieldSize(max); + } + + @Override + public int getMaxRows() throws SQLException { + return callableStatement.getMaxRows(); + } + + @Override + public void setMaxRows(int max) throws SQLException { + callableStatement.setMaxRows(max); + } + + @Override + public void setEscapeProcessing(boolean enable) throws SQLException { + callableStatement.setEscapeProcessing(enable); + } + + @Override + public int getQueryTimeout() throws SQLException { + return callableStatement.getQueryTimeout(); + } + + @Override + public void setQueryTimeout(int seconds) throws SQLException { + callableStatement.setQueryTimeout(seconds); + } + + @Override + public void cancel() throws SQLException { + callableStatement.cancel(); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return callableStatement.getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + callableStatement.clearWarnings(); + } + + @Override + public void setCursorName(String name) throws SQLException { + callableStatement.setCursorName(name); + } + + @Override + public boolean execute(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.execute(interceptState.getSql()); + } + + @Override + public ResultSet getResultSet() throws SQLException { + return new ResultSetProxy(callableStatement.getResultSet(),this.interceptState); + } + + @Override + public int getUpdateCount() throws SQLException { + return callableStatement.getUpdateCount(); + } + + @Override + public boolean getMoreResults() throws SQLException { + return callableStatement.getMoreResults(); + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + callableStatement.setFetchDirection(direction); + } + + @Override + public int getFetchDirection() throws SQLException { + return callableStatement.getFetchDirection(); + } + + @Override + public void setFetchSize(int rows) throws SQLException { + callableStatement.setFetchSize(rows); + } + + @Override + public int getFetchSize() throws SQLException { + return callableStatement.getFetchSize(); + } + + @Override + public int getResultSetConcurrency() throws SQLException { + return callableStatement.getResultSetConcurrency(); + } + + @Override + public int getResultSetType() throws SQLException { + return callableStatement.getResultSetType(); + } + + @Override + public void addBatch(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + callableStatement.addBatch(interceptState.getSql()); + } + + @Override + public void clearBatch() throws SQLException { + callableStatement.clearBatch(); + } + + @Override + public int[] executeBatch() throws SQLException { + return callableStatement.executeBatch(); + } + + @Override + public Connection getConnection() throws SQLException { + return new ConnectionProxy(callableStatement.getConnection()); + } + + @Override + public boolean getMoreResults(int current) throws SQLException { + return callableStatement.getMoreResults(current); + } + + @Override + public ResultSet getGeneratedKeys() throws SQLException { + return callableStatement.getGeneratedKeys(); + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.executeUpdate(interceptState.getSql(), autoGeneratedKeys); + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.executeUpdate(interceptState.getSql(), columnIndexes); + } + + @Override + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.executeUpdate(interceptState.getSql(), columnNames); + } + + @Override + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.execute(interceptState.getSql(), autoGeneratedKeys); + } + + @Override + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.execute(interceptState.getSql(), columnIndexes); + } + + @Override + public boolean execute(String sql, String[] columnNames) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.execute(interceptState.getSql(), columnNames); + } + + @Override + public int getResultSetHoldability() throws SQLException { + return callableStatement.getResultSetHoldability(); + } + + @Override + public boolean isClosed() throws SQLException { + return callableStatement.isClosed(); + } + + @Override + public void setPoolable(boolean poolable) throws SQLException { + callableStatement.setPoolable(poolable); + } + + @Override + public boolean isPoolable() throws SQLException { + return callableStatement.isPoolable(); + } + + @Override + public void closeOnCompletion() throws SQLException { + callableStatement.closeOnCompletion(); + } + + @Override + public boolean isCloseOnCompletion() throws SQLException { + return callableStatement.isCloseOnCompletion(); + } + + @Override + public long getLargeUpdateCount() throws SQLException { + return callableStatement.getLargeUpdateCount(); + } + + @Override + public void setLargeMaxRows(long max) throws SQLException { + callableStatement.setLargeMaxRows(max); + } + + @Override + public long getLargeMaxRows() throws SQLException { + return callableStatement.getLargeMaxRows(); + } + + @Override + public long[] executeLargeBatch() throws SQLException { + return callableStatement.executeLargeBatch(); + } + + @Override + public long executeLargeUpdate(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.executeLargeUpdate(interceptState.getSql()); + } + + @Override + public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.executeLargeUpdate(interceptState.getSql(), autoGeneratedKeys); + } + + @Override + public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.executeLargeUpdate(interceptState.getSql(), columnIndexes); + } + + @Override + public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return callableStatement.executeLargeUpdate(interceptState.getSql(), columnNames); + } + + + @Override + public T unwrap(Class iface) throws SQLException { + return callableStatement.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return callableStatement.isWrapperFor(iface); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/ConnectionProxy.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/ConnectionProxy.java new file mode 100644 index 00000000..72a09567 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/ConnectionProxy.java @@ -0,0 +1,300 @@ +package com.codingapi.springboot.authorization.jdbc.proxy; + +import com.codingapi.springboot.authorization.interceptor.SQLInterceptState; +import com.codingapi.springboot.authorization.interceptor.SQLRunningContext; + +import java.sql.*; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +public class ConnectionProxy implements Connection { + + private final Connection connection; + + public ConnectionProxy(Connection connection) { + this.connection = connection; + } + + private SQLInterceptState interceptState; + + @Override + public Statement createStatement() throws SQLException { + return new StatementProxy(connection.createStatement(), interceptState); + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new PreparedStatementProxy(connection.prepareStatement(interceptState.getSql()),interceptState); + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new CallableStatementProxy(connection.prepareCall(interceptState.getSql()), interceptState); + } + + @Override + public String nativeSQL(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return connection.nativeSQL(interceptState.getSql()); + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + connection.setAutoCommit(autoCommit); + } + + @Override + public boolean getAutoCommit() throws SQLException { + return connection.getAutoCommit(); + } + + @Override + public void commit() throws SQLException { + connection.commit(); + } + + @Override + public void rollback() throws SQLException { + connection.rollback(); + } + + @Override + public void close() throws SQLException { + connection.close(); + } + + @Override + public boolean isClosed() throws SQLException { + return connection.isClosed(); + } + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + return connection.getMetaData(); + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLException { + connection.setReadOnly(readOnly); + } + + @Override + public boolean isReadOnly() throws SQLException { + return connection.isReadOnly(); + } + + @Override + public void setCatalog(String catalog) throws SQLException { + connection.setCatalog(catalog); + } + + @Override + public String getCatalog() throws SQLException { + return connection.getCatalog(); + } + + @Override + public void setTransactionIsolation(int level) throws SQLException { + connection.setTransactionIsolation(level); + } + + @Override + public int getTransactionIsolation() throws SQLException { + return connection.getTransactionIsolation(); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return connection.getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + connection.clearWarnings(); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + return new StatementProxy(connection.createStatement(resultSetType, resultSetConcurrency),this.interceptState); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new PreparedStatementProxy(connection.prepareStatement(interceptState.getSql(), resultSetType, resultSetConcurrency),interceptState); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new CallableStatementProxy(connection.prepareCall(interceptState.getSql(), resultSetType, resultSetConcurrency),interceptState); + } + + @Override + public Map> getTypeMap() throws SQLException { + return connection.getTypeMap(); + } + + @Override + public void setTypeMap(Map> map) throws SQLException { + connection.setTypeMap(map); + } + + @Override + public void setHoldability(int holdability) throws SQLException { + connection.setHoldability(holdability); + } + + @Override + public int getHoldability() throws SQLException { + return connection.getHoldability(); + } + + @Override + public Savepoint setSavepoint() throws SQLException { + return connection.setSavepoint(); + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + return connection.setSavepoint(name); + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + connection.rollback(savepoint); + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + connection.releaseSavepoint(savepoint); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + return new StatementProxy(connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability),interceptState); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new PreparedStatementProxy(connection.prepareStatement(interceptState.getSql(), resultSetType, resultSetConcurrency, resultSetHoldability),interceptState); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new CallableStatementProxy(connection.prepareCall(interceptState.getSql(), resultSetType, resultSetConcurrency, resultSetHoldability),interceptState); + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new PreparedStatementProxy(connection.prepareStatement(interceptState.getSql(), autoGeneratedKeys),interceptState); + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new PreparedStatementProxy(connection.prepareStatement(interceptState.getSql(), columnIndexes),interceptState); + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new PreparedStatementProxy(connection.prepareStatement(interceptState.getSql(), columnNames),interceptState); + } + + @Override + public Clob createClob() throws SQLException { + return connection.createClob(); + } + + @Override + public Blob createBlob() throws SQLException { + return connection.createBlob(); + } + + @Override + public NClob createNClob() throws SQLException { + return connection.createNClob(); + } + + @Override + public SQLXML createSQLXML() throws SQLException { + return connection.createSQLXML(); + } + + @Override + public boolean isValid(int timeout) throws SQLException { + return connection.isValid(timeout); + } + + @Override + public void setClientInfo(String name, String value) throws SQLClientInfoException { + connection.setClientInfo(name, value); + } + + @Override + public void setClientInfo(Properties properties) throws SQLClientInfoException { + connection.setClientInfo(properties); + } + + @Override + public String getClientInfo(String name) throws SQLException { + return connection.getClientInfo(name); + } + + @Override + public Properties getClientInfo() throws SQLException { + return connection.getClientInfo(); + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + return connection.createArrayOf(typeName, elements); + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + return connection.createStruct(typeName, attributes); + } + + @Override + public void setSchema(String schema) throws SQLException { + connection.setSchema(schema); + } + + @Override + public String getSchema() throws SQLException { + return connection.getSchema(); + } + + @Override + public void abort(Executor executor) throws SQLException { + connection.abort(executor); + } + + @Override + public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { + connection.setNetworkTimeout(executor, milliseconds); + } + + @Override + public int getNetworkTimeout() throws SQLException { + return connection.getNetworkTimeout(); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return connection.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return connection.isWrapperFor(iface); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/PreparedStatementProxy.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/PreparedStatementProxy.java new file mode 100644 index 00000000..89c17acd --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/PreparedStatementProxy.java @@ -0,0 +1,585 @@ +package com.codingapi.springboot.authorization.jdbc.proxy; + +import com.codingapi.springboot.authorization.interceptor.SQLInterceptState; +import com.codingapi.springboot.authorization.interceptor.SQLRunningContext; +import lombok.AllArgsConstructor; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; +import java.util.Calendar; + +@AllArgsConstructor +public class PreparedStatementProxy implements PreparedStatement { + + private final PreparedStatement preparedStatement; + + private SQLInterceptState interceptState; + + + @Override + public ResultSet executeQuery() throws SQLException { + return new ResultSetProxy(preparedStatement.executeQuery(),interceptState); + } + + @Override + public int executeUpdate() throws SQLException { + return preparedStatement.executeUpdate(); + } + + @Override + public void setNull(int parameterIndex, int sqlType) throws SQLException { + preparedStatement.setNull(parameterIndex, sqlType); + } + + @Override + public void setBoolean(int parameterIndex, boolean x) throws SQLException { + preparedStatement.setBoolean(parameterIndex, x); + } + + @Override + public void setByte(int parameterIndex, byte x) throws SQLException { + preparedStatement.setByte(parameterIndex, x); + } + + @Override + public void setShort(int parameterIndex, short x) throws SQLException { + preparedStatement.setShort(parameterIndex, x); + } + + @Override + public void setInt(int parameterIndex, int x) throws SQLException { + preparedStatement.setInt(parameterIndex, x); + } + + @Override + public void setLong(int parameterIndex, long x) throws SQLException { + preparedStatement.setLong(parameterIndex, x); + } + + @Override + public void setFloat(int parameterIndex, float x) throws SQLException { + preparedStatement.setFloat(parameterIndex, x); + } + + @Override + public void setDouble(int parameterIndex, double x) throws SQLException { + preparedStatement.setDouble(parameterIndex, x); + } + + @Override + public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { + preparedStatement.setBigDecimal(parameterIndex, x); + } + + @Override + public void setString(int parameterIndex, String x) throws SQLException { + preparedStatement.setString(parameterIndex, x); + } + + @Override + public void setBytes(int parameterIndex, byte[] x) throws SQLException { + preparedStatement.setBytes(parameterIndex, x); + } + + @Override + public void setDate(int parameterIndex, Date x) throws SQLException { + preparedStatement.setDate(parameterIndex, x); + } + + @Override + public void setTime(int parameterIndex, Time x) throws SQLException { + preparedStatement.setTime(parameterIndex, x); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { + preparedStatement.setTimestamp(parameterIndex, x); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { + preparedStatement.setAsciiStream(parameterIndex, x, length); + } + + @Override + public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { + preparedStatement.setUnicodeStream(parameterIndex, x, length); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { + preparedStatement.setBinaryStream(parameterIndex, x, length); + } + + @Override + public void clearParameters() throws SQLException { + preparedStatement.clearParameters(); + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { + preparedStatement.setObject(parameterIndex, x, targetSqlType); + } + + @Override + public void setObject(int parameterIndex, Object x) throws SQLException { + preparedStatement.setObject(parameterIndex, x); + } + + @Override + public boolean execute() throws SQLException { + return preparedStatement.execute(); + } + + @Override + public void addBatch() throws SQLException { + preparedStatement.addBatch(); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { + preparedStatement.setCharacterStream(parameterIndex, reader, length); + } + + @Override + public void setRef(int parameterIndex, Ref x) throws SQLException { + preparedStatement.setRef(parameterIndex, x); + } + + @Override + public void setBlob(int parameterIndex, Blob x) throws SQLException { + preparedStatement.setBlob(parameterIndex, x); + } + + @Override + public void setClob(int parameterIndex, Clob x) throws SQLException { + preparedStatement.setClob(parameterIndex, x); + } + + @Override + public void setArray(int parameterIndex, Array x) throws SQLException { + preparedStatement.setArray(parameterIndex, x); + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return preparedStatement.getMetaData(); + } + + @Override + public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { + preparedStatement.setDate(parameterIndex, x, cal); + } + + @Override + public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { + preparedStatement.setTime(parameterIndex, x, cal); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { + preparedStatement.setTimestamp(parameterIndex, x, cal); + } + + @Override + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { + preparedStatement.setNull(parameterIndex, sqlType, typeName); + } + + @Override + public void setURL(int parameterIndex, URL x) throws SQLException { + preparedStatement.setURL(parameterIndex, x); + } + + @Override + public ParameterMetaData getParameterMetaData() throws SQLException { + return preparedStatement.getParameterMetaData(); + } + + @Override + public void setRowId(int parameterIndex, RowId x) throws SQLException { + preparedStatement.setRowId(parameterIndex, x); + } + + @Override + public void setNString(int parameterIndex, String value) throws SQLException { + preparedStatement.setNString(parameterIndex, value); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { + preparedStatement.setNCharacterStream(parameterIndex, value, length); + } + + @Override + public void setNClob(int parameterIndex, NClob value) throws SQLException { + preparedStatement.setNClob(parameterIndex, value); + } + + @Override + public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { + preparedStatement.setClob(parameterIndex, reader, length); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { + preparedStatement.setBlob(parameterIndex, inputStream, length); + } + + @Override + public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { + preparedStatement.setNClob(parameterIndex, reader, length); + } + + @Override + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + preparedStatement.setSQLXML(parameterIndex, xmlObject); + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { + preparedStatement.setObject(parameterIndex, x, targetSqlType, scaleOrLength); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + preparedStatement.setAsciiStream(parameterIndex, x, length); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + preparedStatement.setBinaryStream(parameterIndex, x, length); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { + preparedStatement.setCharacterStream(parameterIndex, reader, length); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + preparedStatement.setAsciiStream(parameterIndex, x); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + preparedStatement.setBinaryStream(parameterIndex, x); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + preparedStatement.setCharacterStream(parameterIndex, reader); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + preparedStatement.setNCharacterStream(parameterIndex, value); + } + + @Override + public void setClob(int parameterIndex, Reader reader) throws SQLException { + preparedStatement.setClob(parameterIndex, reader); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { + preparedStatement.setBlob(parameterIndex, inputStream); + } + + @Override + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + preparedStatement.setNClob(parameterIndex, reader); + } + + @Override + public void setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException { + preparedStatement.setObject(parameterIndex, x, targetSqlType, scaleOrLength); + } + + @Override + public void setObject(int parameterIndex, Object x, SQLType targetSqlType) throws SQLException { + preparedStatement.setObject(parameterIndex, x, targetSqlType); + } + + @Override + public long executeLargeUpdate() throws SQLException { + return preparedStatement.executeLargeUpdate(); + } + + @Override + public ResultSet executeQuery(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new ResultSetProxy(preparedStatement.executeQuery(interceptState.getSql()),interceptState); + } + + @Override + public int executeUpdate(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.executeUpdate(interceptState.getSql()); + } + + @Override + public void close() throws SQLException { + preparedStatement.close(); + } + + @Override + public int getMaxFieldSize() throws SQLException { + return preparedStatement.getMaxFieldSize(); + } + + @Override + public void setMaxFieldSize(int max) throws SQLException { + preparedStatement.setMaxFieldSize(max); + } + + @Override + public int getMaxRows() throws SQLException { + return preparedStatement.getMaxRows(); + } + + @Override + public void setMaxRows(int max) throws SQLException { + preparedStatement.setMaxRows(max); + } + + @Override + public void setEscapeProcessing(boolean enable) throws SQLException { + preparedStatement.setEscapeProcessing(enable); + } + + @Override + public int getQueryTimeout() throws SQLException { + return preparedStatement.getQueryTimeout(); + } + + @Override + public void setQueryTimeout(int seconds) throws SQLException { + preparedStatement.setQueryTimeout(seconds); + } + + @Override + public void cancel() throws SQLException { + preparedStatement.cancel(); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return preparedStatement.getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + preparedStatement.clearWarnings(); + } + + @Override + public void setCursorName(String name) throws SQLException { + preparedStatement.setCursorName(name); + } + + @Override + public boolean execute(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.execute(interceptState.getSql()); + } + + @Override + public ResultSet getResultSet() throws SQLException { + return new ResultSetProxy(preparedStatement.getResultSet(),interceptState); + } + + @Override + public int getUpdateCount() throws SQLException { + return preparedStatement.getUpdateCount(); + } + + @Override + public boolean getMoreResults() throws SQLException { + return preparedStatement.getMoreResults(); + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + preparedStatement.setFetchDirection(direction); + } + + @Override + public int getFetchDirection() throws SQLException { + return preparedStatement.getFetchDirection(); + } + + @Override + public void setFetchSize(int rows) throws SQLException { + preparedStatement.setFetchSize(rows); + } + + @Override + public int getFetchSize() throws SQLException { + return preparedStatement.getFetchSize(); + } + + @Override + public int getResultSetConcurrency() throws SQLException { + return preparedStatement.getResultSetConcurrency(); + } + + @Override + public int getResultSetType() throws SQLException { + return preparedStatement.getResultSetType(); + } + + @Override + public void addBatch(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + preparedStatement.addBatch(interceptState.getSql()); + } + + @Override + public void clearBatch() throws SQLException { + preparedStatement.clearBatch(); + } + + @Override + public int[] executeBatch() throws SQLException { + return preparedStatement.executeBatch(); + } + + @Override + public Connection getConnection() throws SQLException { + return new ConnectionProxy(preparedStatement.getConnection()); + } + + @Override + public boolean getMoreResults(int current) throws SQLException { + return preparedStatement.getMoreResults(current); + } + + @Override + public ResultSet getGeneratedKeys() throws SQLException { + return new ResultSetProxy(preparedStatement.getGeneratedKeys(),interceptState); + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.executeUpdate(interceptState.getSql(), autoGeneratedKeys); + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.executeUpdate(interceptState.getSql(), columnIndexes); + } + + @Override + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.executeUpdate(interceptState.getSql(), columnNames); + } + + @Override + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.execute(interceptState.getSql(), autoGeneratedKeys); + } + + @Override + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.execute(interceptState.getSql(), columnIndexes); + } + + @Override + public boolean execute(String sql, String[] columnNames) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.execute(interceptState.getSql(), columnNames); + } + + @Override + public int getResultSetHoldability() throws SQLException { + return preparedStatement.getResultSetHoldability(); + } + + @Override + public boolean isClosed() throws SQLException { + return preparedStatement.isClosed(); + } + + @Override + public void setPoolable(boolean poolable) throws SQLException { + preparedStatement.setPoolable(poolable); + } + + @Override + public boolean isPoolable() throws SQLException { + return preparedStatement.isPoolable(); + } + + @Override + public void closeOnCompletion() throws SQLException { + preparedStatement.closeOnCompletion(); + } + + @Override + public boolean isCloseOnCompletion() throws SQLException { + return preparedStatement.isCloseOnCompletion(); + } + + @Override + public long getLargeUpdateCount() throws SQLException { + return preparedStatement.getLargeUpdateCount(); + } + + @Override + public void setLargeMaxRows(long max) throws SQLException { + preparedStatement.setLargeMaxRows(max); + } + + @Override + public long getLargeMaxRows() throws SQLException { + return preparedStatement.getLargeMaxRows(); + } + + @Override + public long[] executeLargeBatch() throws SQLException { + return preparedStatement.executeLargeBatch(); + } + + @Override + public long executeLargeUpdate(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.executeLargeUpdate(interceptState.getSql()); + } + + @Override + public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.executeLargeUpdate(interceptState.getSql(), autoGeneratedKeys); + } + + @Override + public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.executeLargeUpdate(interceptState.getSql(), columnIndexes); + } + + @Override + public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return preparedStatement.executeLargeUpdate(interceptState.getSql(), columnNames); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return preparedStatement.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return preparedStatement.isWrapperFor(iface); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/ResultSetProxy.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/ResultSetProxy.java new file mode 100644 index 00000000..40c72b09 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/ResultSetProxy.java @@ -0,0 +1,1180 @@ +package com.codingapi.springboot.authorization.jdbc.proxy; + +import com.codingapi.springboot.authorization.handler.ColumnHandlerContext; +import com.codingapi.springboot.authorization.interceptor.SQLInterceptState; +import lombok.extern.slf4j.Slf4j; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +public class ResultSetProxy implements ResultSet { + + private final ResultSet resultSet; + private final ResultSetMetaData metaData; + private final SQLInterceptState interceptState; + + private final Map columnLabelMap = new HashMap<>(); + + public ResultSetProxy(ResultSet resultSet, SQLInterceptState interceptState) throws SQLException { + this.resultSet = resultSet; + this.metaData = resultSet.getMetaData(); + this.interceptState = interceptState; + int columnCount = metaData.getColumnCount(); + for (int i = 1; i <= columnCount; i++) { + String columnLabel = metaData.getColumnLabel(i); + columnLabelMap.put(columnLabel.toUpperCase(), i); + } + } + + @Override + public boolean next() throws SQLException { + return resultSet.next(); + } + + @Override + public void close() throws SQLException { + resultSet.close(); + } + + @Override + public boolean wasNull() throws SQLException { + return resultSet.wasNull(); + } + + @Override + public String getString(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getString(interceptState, columnIndex, tableName, columnName, resultSet.getString(columnIndex)); + } + + @Override + public boolean getBoolean(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBoolean(interceptState, columnIndex, tableName, columnName, resultSet.getBoolean(columnIndex)); + } + + @Override + public byte getByte(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getByte(interceptState, columnIndex, tableName, columnName, resultSet.getByte(columnIndex)); + } + + @Override + public short getShort(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getShort(interceptState, columnIndex, tableName, columnName, resultSet.getShort(columnIndex)); + } + + @Override + public int getInt(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getInt(interceptState, columnIndex, tableName, columnName, resultSet.getInt(columnIndex)); + } + + @Override + public long getLong(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getLong(interceptState, columnIndex, tableName, columnName, resultSet.getLong(columnIndex)); + } + + @Override + public float getFloat(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getFloat(interceptState, columnIndex, tableName, columnName, resultSet.getFloat(columnIndex)); + } + + @Override + public double getDouble(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getDouble(interceptState, columnIndex, tableName, columnName, resultSet.getDouble(columnIndex)); + } + + @Override + public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBigDecimal(interceptState, columnIndex, tableName, columnName, resultSet.getBigDecimal(columnIndex, scale)); + } + + @Override + public byte[] getBytes(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBytes(interceptState, columnIndex, tableName, columnName, resultSet.getBytes(columnIndex)); + } + + @Override + public Date getDate(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getDate(interceptState, columnIndex, tableName, columnName, resultSet.getDate(columnIndex)); + } + + @Override + public Time getTime(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getTime(interceptState, columnIndex, tableName, columnName, resultSet.getTime(columnIndex)); + } + + @Override + public Timestamp getTimestamp(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getTimestamp(interceptState, columnIndex, tableName, columnName, resultSet.getTimestamp(columnIndex)); + } + + @Override + public InputStream getAsciiStream(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getAsciiStream(interceptState, columnIndex, tableName, columnName, resultSet.getAsciiStream(columnIndex)); + } + + @Override + public InputStream getUnicodeStream(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getUnicodeStream(interceptState, columnIndex, tableName, columnName, resultSet.getUnicodeStream(columnIndex)); + } + + @Override + public InputStream getBinaryStream(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBinaryStream(interceptState, columnIndex, tableName, columnName, resultSet.getBinaryStream(columnIndex)); + } + + @Override + public String getString(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getString(interceptState, columnIndex, tableName, columnName, resultSet.getString(columnIndex)); + } + + @Override + public boolean getBoolean(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBoolean(interceptState, columnIndex, tableName, columnName, resultSet.getBoolean(columnIndex)); + } + + @Override + public byte getByte(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getByte(interceptState, columnIndex, tableName, columnName, resultSet.getByte(columnIndex)); + } + + @Override + public short getShort(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getShort(interceptState, columnIndex, tableName, columnName, resultSet.getShort(columnIndex)); + } + + @Override + public int getInt(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getInt(interceptState, columnIndex, tableName, columnName, resultSet.getInt(columnIndex)); + } + + @Override + public long getLong(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getLong(interceptState, columnIndex, tableName, columnName, resultSet.getLong(columnIndex)); + } + + @Override + public float getFloat(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getFloat(interceptState, columnIndex, tableName, columnName, resultSet.getFloat(columnIndex)); + } + + @Override + public double getDouble(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getDouble(interceptState, columnIndex, tableName, columnName, resultSet.getDouble(columnIndex)); + } + + @Override + public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBigDecimal(interceptState, columnIndex, tableName, columnName, resultSet.getBigDecimal(columnIndex, scale)); + } + + @Override + public byte[] getBytes(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBytes(interceptState, columnIndex, tableName, columnName, resultSet.getBytes(columnIndex)); + } + + @Override + public Date getDate(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getDate(interceptState, columnIndex, tableName, columnName, resultSet.getDate(columnIndex)); + } + + @Override + public Time getTime(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getTime(interceptState, columnIndex, tableName, columnName, resultSet.getTime(columnIndex)); + } + + @Override + public Timestamp getTimestamp(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getTimestamp(interceptState, columnIndex, tableName, columnName, resultSet.getTimestamp(columnIndex)); + } + + @Override + public InputStream getAsciiStream(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getAsciiStream(interceptState, columnIndex, tableName, columnName, resultSet.getAsciiStream(columnIndex)); + } + + @Override + public InputStream getUnicodeStream(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getUnicodeStream(interceptState, columnIndex, tableName, columnName, resultSet.getUnicodeStream(columnIndex)); + } + + @Override + public InputStream getBinaryStream(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBinaryStream(interceptState, columnIndex, tableName, columnName, resultSet.getBinaryStream(columnIndex)); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return resultSet.getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + resultSet.clearWarnings(); + } + + @Override + public String getCursorName() throws SQLException { + return resultSet.getCursorName(); + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return resultSet.getMetaData(); + } + + @Override + public Object getObject(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getObject(interceptState, columnIndex, tableName, columnName, resultSet.getObject(columnIndex)); + } + + @Override + public Object getObject(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getObject(interceptState, columnIndex, tableName, columnName, resultSet.getObject(columnIndex)); + } + + @Override + public int findColumn(String columnLabel) throws SQLException { + return resultSet.findColumn(columnLabel); + } + + @Override + public Reader getCharacterStream(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getCharacterStream(interceptState, columnIndex, tableName, columnName, resultSet.getCharacterStream(columnIndex)); + } + + @Override + public Reader getCharacterStream(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getCharacterStream(interceptState, columnIndex, tableName, columnName, resultSet.getCharacterStream(columnIndex)); + } + + @Override + public BigDecimal getBigDecimal(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBigDecimal(interceptState, columnIndex, tableName, columnName, resultSet.getBigDecimal(columnIndex)); + } + + @Override + public BigDecimal getBigDecimal(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBigDecimal(interceptState, columnIndex, tableName, columnName, resultSet.getBigDecimal(columnIndex)); + } + + @Override + public boolean isBeforeFirst() throws SQLException { + return resultSet.isBeforeFirst(); + } + + @Override + public boolean isAfterLast() throws SQLException { + return resultSet.isAfterLast(); + } + + @Override + public boolean isFirst() throws SQLException { + return resultSet.isFirst(); + } + + @Override + public boolean isLast() throws SQLException { + return resultSet.isLast(); + } + + @Override + public void beforeFirst() throws SQLException { + resultSet.beforeFirst(); + } + + @Override + public void afterLast() throws SQLException { + resultSet.afterLast(); + } + + @Override + public boolean first() throws SQLException { + return resultSet.first(); + } + + @Override + public boolean last() throws SQLException { + return resultSet.last(); + } + + @Override + public int getRow() throws SQLException { + return resultSet.getRow(); + } + + @Override + public boolean absolute(int row) throws SQLException { + return resultSet.absolute(row); + } + + @Override + public boolean relative(int rows) throws SQLException { + return resultSet.relative(rows); + } + + @Override + public boolean previous() throws SQLException { + return resultSet.previous(); + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + resultSet.setFetchDirection(direction); + } + + @Override + public int getFetchDirection() throws SQLException { + return resultSet.getFetchDirection(); + } + + @Override + public void setFetchSize(int rows) throws SQLException { + resultSet.setFetchSize(rows); + } + + @Override + public int getFetchSize() throws SQLException { + return resultSet.getFetchSize(); + } + + @Override + public int getType() throws SQLException { + return resultSet.getType(); + } + + @Override + public int getConcurrency() throws SQLException { + return resultSet.getConcurrency(); + } + + @Override + public boolean rowUpdated() throws SQLException { + return resultSet.rowUpdated(); + } + + @Override + public boolean rowInserted() throws SQLException { + return resultSet.rowInserted(); + } + + @Override + public boolean rowDeleted() throws SQLException { + return resultSet.rowDeleted(); + } + + @Override + public void updateNull(int columnIndex) throws SQLException { + resultSet.updateNull(columnIndex); + } + + @Override + public void updateBoolean(int columnIndex, boolean x) throws SQLException { + resultSet.updateBoolean(columnIndex, x); + } + + @Override + public void updateByte(int columnIndex, byte x) throws SQLException { + resultSet.updateByte(columnIndex, x); + } + + @Override + public void updateShort(int columnIndex, short x) throws SQLException { + resultSet.updateShort(columnIndex, x); + } + + @Override + public void updateInt(int columnIndex, int x) throws SQLException { + resultSet.updateInt(columnIndex, x); + } + + @Override + public void updateLong(int columnIndex, long x) throws SQLException { + resultSet.updateLong(columnIndex, x); + } + + @Override + public void updateFloat(int columnIndex, float x) throws SQLException { + resultSet.updateFloat(columnIndex, x); + } + + @Override + public void updateDouble(int columnIndex, double x) throws SQLException { + resultSet.updateDouble(columnIndex, x); + } + + @Override + public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { + resultSet.updateBigDecimal(columnIndex, x); + } + + @Override + public void updateString(int columnIndex, String x) throws SQLException { + resultSet.updateString(columnIndex, x); + } + + @Override + public void updateBytes(int columnIndex, byte[] x) throws SQLException { + resultSet.updateBytes(columnIndex, x); + } + + @Override + public void updateDate(int columnIndex, Date x) throws SQLException { + resultSet.updateDate(columnIndex, x); + } + + @Override + public void updateTime(int columnIndex, Time x) throws SQLException { + resultSet.updateTime(columnIndex, x); + } + + @Override + public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { + resultSet.updateTimestamp(columnIndex, x); + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { + resultSet.updateAsciiStream(columnIndex, x, length); + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { + resultSet.updateBinaryStream(columnIndex, x, length); + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { + resultSet.updateCharacterStream(columnIndex, x, length); + } + + @Override + public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException { + resultSet.updateObject(columnIndex, x, scaleOrLength); + } + + @Override + public void updateObject(int columnIndex, Object x) throws SQLException { + resultSet.updateObject(columnIndex, x); + } + + @Override + public void updateNull(String columnLabel) throws SQLException { + resultSet.updateNull(columnLabel); + } + + @Override + public void updateBoolean(String columnLabel, boolean x) throws SQLException { + resultSet.updateBoolean(columnLabel, x); + } + + @Override + public void updateByte(String columnLabel, byte x) throws SQLException { + resultSet.updateByte(columnLabel, x); + } + + @Override + public void updateShort(String columnLabel, short x) throws SQLException { + resultSet.updateShort(columnLabel, x); + } + + @Override + public void updateInt(String columnLabel, int x) throws SQLException { + resultSet.updateInt(columnLabel, x); + } + + @Override + public void updateLong(String columnLabel, long x) throws SQLException { + resultSet.updateLong(columnLabel, x); + } + + @Override + public void updateFloat(String columnLabel, float x) throws SQLException { + resultSet.updateFloat(columnLabel, x); + } + + @Override + public void updateDouble(String columnLabel, double x) throws SQLException { + resultSet.updateDouble(columnLabel, x); + } + + @Override + public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException { + resultSet.updateBigDecimal(columnLabel, x); + } + + @Override + public void updateString(String columnLabel, String x) throws SQLException { + resultSet.updateString(columnLabel, x); + } + + @Override + public void updateBytes(String columnLabel, byte[] x) throws SQLException { + resultSet.updateBytes(columnLabel, x); + } + + @Override + public void updateDate(String columnLabel, Date x) throws SQLException { + resultSet.updateDate(columnLabel, x); + } + + @Override + public void updateTime(String columnLabel, Time x) throws SQLException { + resultSet.updateTime(columnLabel, x); + } + + @Override + public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException { + resultSet.updateTimestamp(columnLabel, x); + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException { + resultSet.updateAsciiStream(columnLabel, x, length); + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException { + resultSet.updateBinaryStream(columnLabel, x, length); + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException { + resultSet.updateCharacterStream(columnLabel, reader, length); + } + + @Override + public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException { + resultSet.updateObject(columnLabel, x, scaleOrLength); + } + + @Override + public void updateObject(String columnLabel, Object x) throws SQLException { + resultSet.updateObject(columnLabel, x); + } + + @Override + public void insertRow() throws SQLException { + resultSet.insertRow(); + } + + @Override + public void updateRow() throws SQLException { + resultSet.updateRow(); + } + + @Override + public void deleteRow() throws SQLException { + resultSet.deleteRow(); + } + + @Override + public void refreshRow() throws SQLException { + resultSet.refreshRow(); + } + + @Override + public void cancelRowUpdates() throws SQLException { + resultSet.cancelRowUpdates(); + } + + @Override + public void moveToInsertRow() throws SQLException { + resultSet.moveToInsertRow(); + } + + @Override + public void moveToCurrentRow() throws SQLException { + resultSet.moveToCurrentRow(); + } + + @Override + public Statement getStatement() throws SQLException { + return resultSet.getStatement(); + } + + @Override + public Object getObject(int columnIndex, Map> map) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getObject(interceptState, columnIndex, tableName, columnName, resultSet.getDate(columnIndex)); + } + + @Override + public Ref getRef(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getRef(interceptState, columnIndex, tableName, columnName, resultSet.getRef(columnIndex)); + } + + @Override + public Blob getBlob(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBlob(interceptState, columnIndex, tableName, columnName, resultSet.getBlob(columnIndex)); + } + + @Override + public Clob getClob(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getClob(interceptState, columnIndex, tableName, columnName, resultSet.getClob(columnIndex)); + } + + @Override + public Array getArray(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getArray(interceptState, columnIndex, tableName, columnName, resultSet.getArray(columnIndex)); + } + + @Override + public Object getObject(String columnLabel, Map> map) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getObject(interceptState, columnIndex, tableName, columnName, resultSet.getObject(columnIndex)); + } + + @Override + public Ref getRef(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getRef(interceptState, columnIndex, tableName, columnName, resultSet.getRef(columnIndex)); + } + + @Override + public Blob getBlob(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getBlob(interceptState, columnIndex, tableName, columnName, resultSet.getBlob(columnIndex)); + } + + @Override + public Clob getClob(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getClob(interceptState, columnIndex, tableName, columnName, resultSet.getClob(columnIndex)); + } + + @Override + public Array getArray(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getArray(interceptState, columnIndex, tableName, columnName, resultSet.getArray(columnIndex)); + } + + @Override + public Date getDate(int columnIndex, Calendar cal) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getDate(interceptState, columnIndex, tableName, columnName, resultSet.getDate(columnIndex, cal)); + } + + @Override + public Date getDate(String columnLabel, Calendar cal) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getDate(interceptState, columnIndex, tableName, columnName, resultSet.getDate(columnIndex, cal)); + } + + @Override + public Time getTime(int columnIndex, Calendar cal) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getTime(interceptState, columnIndex, tableName, columnName, resultSet.getTime(columnIndex, cal)); + } + + @Override + public Time getTime(String columnLabel, Calendar cal) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getTime(interceptState, columnIndex, tableName, columnName, resultSet.getTime(columnIndex, cal)); + } + + @Override + public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getTimestamp(interceptState, columnIndex, tableName, columnName, resultSet.getTimestamp(columnIndex, cal)); + } + + @Override + public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getTimestamp(interceptState, columnIndex, tableName, columnName, resultSet.getTimestamp(columnIndex, cal)); + } + + @Override + public URL getURL(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getURL(interceptState, columnIndex, tableName, columnName, resultSet.getURL(columnIndex)); + } + + @Override + public URL getURL(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getURL(interceptState, columnIndex, tableName, columnName, resultSet.getURL(columnIndex)); + } + + @Override + public void updateRef(int columnIndex, Ref x) throws SQLException { + resultSet.updateRef(columnIndex, x); + } + + @Override + public void updateRef(String columnLabel, Ref x) throws SQLException { + resultSet.updateRef(columnLabel, x); + } + + @Override + public void updateBlob(int columnIndex, Blob x) throws SQLException { + resultSet.updateBlob(columnIndex, x); + } + + @Override + public void updateBlob(String columnLabel, Blob x) throws SQLException { + resultSet.updateBlob(columnLabel, x); + } + + @Override + public void updateClob(int columnIndex, Clob x) throws SQLException { + resultSet.updateClob(columnIndex, x); + } + + @Override + public void updateClob(String columnLabel, Clob x) throws SQLException { + resultSet.updateClob(columnLabel, x); + } + + @Override + public void updateArray(int columnIndex, Array x) throws SQLException { + resultSet.updateArray(columnIndex, x); + } + + @Override + public void updateArray(String columnLabel, Array x) throws SQLException { + resultSet.updateArray(columnLabel, x); + } + + @Override + public RowId getRowId(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getRowId(interceptState, columnIndex, tableName, columnName, resultSet.getRowId(columnIndex)); + } + + @Override + public RowId getRowId(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getRowId(interceptState, columnIndex, tableName, columnName, resultSet.getRowId(columnIndex)); + } + + @Override + public void updateRowId(int columnIndex, RowId x) throws SQLException { + resultSet.updateRowId(columnIndex, x); + } + + @Override + public void updateRowId(String columnLabel, RowId x) throws SQLException { + resultSet.updateRowId(columnLabel, x); + } + + @Override + public int getHoldability() throws SQLException { + return resultSet.getHoldability(); + } + + @Override + public boolean isClosed() throws SQLException { + return resultSet.isClosed(); + } + + @Override + public void updateNString(int columnIndex, String nString) throws SQLException { + resultSet.updateNString(columnIndex, nString); + } + + @Override + public void updateNString(String columnLabel, String nString) throws SQLException { + resultSet.updateNString(columnLabel, nString); + } + + @Override + public void updateNClob(int columnIndex, NClob nClob) throws SQLException { + resultSet.updateNClob(columnIndex, nClob); + } + + @Override + public void updateNClob(String columnLabel, NClob nClob) throws SQLException { + resultSet.updateNClob(columnLabel, nClob); + } + + @Override + public NClob getNClob(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getNClob(interceptState, columnIndex, tableName, columnName, resultSet.getNClob(columnIndex)); + } + + @Override + public NClob getNClob(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getNClob(interceptState, columnIndex, tableName, columnName, resultSet.getNClob(columnIndex)); + } + + @Override + public SQLXML getSQLXML(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getSQLXML(interceptState, columnIndex, tableName, columnName, resultSet.getSQLXML(columnIndex)); + } + + @Override + public SQLXML getSQLXML(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getSQLXML(interceptState, columnIndex, tableName, columnName, resultSet.getSQLXML(columnIndex)); + } + + @Override + public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { + resultSet.updateSQLXML(columnIndex, xmlObject); + } + + @Override + public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { + resultSet.updateSQLXML(columnLabel, xmlObject); + } + + @Override + public String getNString(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getNString(interceptState, columnIndex, tableName, columnName, resultSet.getNString(columnIndex)); + } + + @Override + public String getNString(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getNString(interceptState, columnIndex, tableName, columnName, resultSet.getNString(columnIndex)); + } + + @Override + public Reader getNCharacterStream(int columnIndex) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getNCharacterStream(interceptState, columnIndex, tableName, columnName, resultSet.getNCharacterStream(columnIndex)); + } + + @Override + public Reader getNCharacterStream(String columnLabel) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getNCharacterStream(interceptState, columnIndex, tableName, columnName, resultSet.getNCharacterStream(columnIndex)); + } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + resultSet.updateNCharacterStream(columnIndex, x, length); + } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { + resultSet.updateNCharacterStream(columnLabel, reader, length); + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { + resultSet.updateAsciiStream(columnIndex, x, length); + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { + resultSet.updateBinaryStream(columnIndex, x, length); + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + resultSet.updateCharacterStream(columnIndex, x, length); + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { + resultSet.updateAsciiStream(columnLabel, x, length); + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { + resultSet.updateBinaryStream(columnLabel, x, length); + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { + resultSet.updateCharacterStream(columnLabel, reader, length); + } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { + resultSet.updateBlob(columnIndex, inputStream, length); + } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { + resultSet.updateBlob(columnLabel, inputStream, length); + } + + @Override + public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { + resultSet.updateClob(columnIndex, reader, length); + } + + @Override + public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { + resultSet.updateClob(columnLabel, reader, length); + } + + @Override + public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { + resultSet.updateNClob(columnIndex, reader, length); + } + + @Override + public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { + resultSet.updateNClob(columnLabel, reader, length); + } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { + resultSet.updateNCharacterStream(columnIndex, x); + } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { + resultSet.updateNCharacterStream(columnLabel, reader); + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { + resultSet.updateAsciiStream(columnIndex, x); + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { + resultSet.updateBinaryStream(columnIndex, x); + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { + resultSet.updateCharacterStream(columnIndex, x); + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { + resultSet.updateAsciiStream(columnLabel, x); + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { + resultSet.updateBinaryStream(columnLabel, x); + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { + resultSet.updateCharacterStream(columnLabel, reader); + } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { + resultSet.updateBlob(columnIndex, inputStream); + } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { + resultSet.updateBlob(columnLabel, inputStream); + } + + @Override + public void updateClob(int columnIndex, Reader reader) throws SQLException { + resultSet.updateClob(columnIndex, reader); + } + + @Override + public void updateClob(String columnLabel, Reader reader) throws SQLException { + resultSet.updateClob(columnLabel, reader); + } + + @Override + public void updateNClob(int columnIndex, Reader reader) throws SQLException { + resultSet.updateNClob(columnIndex, reader); + } + + @Override + public void updateNClob(String columnLabel, Reader reader) throws SQLException { + resultSet.updateNClob(columnLabel, reader); + } + + @Override + public T getObject(int columnIndex, Class type) throws SQLException { + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getObject(interceptState, columnIndex, tableName, columnName, resultSet.getObject(columnIndex, type), type); + } + + @Override + public T getObject(String columnLabel, Class type) throws SQLException { + int columnIndex = columnLabelMap.get(columnLabel.toUpperCase()); + String tableName = metaData.getTableName(columnIndex); + String columnName = metaData.getColumnName(columnIndex); + return ColumnHandlerContext.getInstance().getObject(interceptState, columnIndex, tableName, columnName, resultSet.getObject(columnIndex, type), type); + } + + @Override + public void updateObject(int columnIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException { + resultSet.updateObject(columnIndex, x, targetSqlType, scaleOrLength); + } + + @Override + public void updateObject(String columnLabel, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException { + resultSet.updateObject(columnLabel, x, targetSqlType, scaleOrLength); + } + + @Override + public void updateObject(int columnIndex, Object x, SQLType targetSqlType) throws SQLException { + resultSet.updateObject(columnIndex, x, targetSqlType); + } + + @Override + public void updateObject(String columnLabel, Object x, SQLType targetSqlType) throws SQLException { + resultSet.updateObject(columnLabel, x, targetSqlType); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return resultSet.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return resultSet.isWrapperFor(iface); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/StatementProxy.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/StatementProxy.java new file mode 100644 index 00000000..99af9be9 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/proxy/StatementProxy.java @@ -0,0 +1,290 @@ +package com.codingapi.springboot.authorization.jdbc.proxy; + +import com.codingapi.springboot.authorization.interceptor.SQLInterceptState; +import com.codingapi.springboot.authorization.interceptor.SQLRunningContext; +import lombok.AllArgsConstructor; + +import java.sql.*; + +@AllArgsConstructor +public class StatementProxy implements Statement { + + private final Statement statement; + private SQLInterceptState interceptState; + + + + @Override + public ResultSet executeQuery(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return new ResultSetProxy(statement.executeQuery(interceptState.getSql()), interceptState); + } + + @Override + public int executeUpdate(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.executeUpdate(interceptState.getSql()); + } + + @Override + public void close() throws SQLException { + statement.close(); + } + + @Override + public int getMaxFieldSize() throws SQLException { + return statement.getMaxFieldSize(); + } + + @Override + public void setMaxFieldSize(int max) throws SQLException { + statement.setMaxFieldSize(max); + } + + @Override + public int getMaxRows() throws SQLException { + return statement.getMaxRows(); + } + + @Override + public void setMaxRows(int max) throws SQLException { + statement.setMaxRows(max); + } + + @Override + public void setEscapeProcessing(boolean enable) throws SQLException { + statement.setEscapeProcessing(enable); + } + + @Override + public int getQueryTimeout() throws SQLException { + return statement.getQueryTimeout(); + } + + @Override + public void setQueryTimeout(int seconds) throws SQLException { + statement.setQueryTimeout(seconds); + } + + @Override + public void cancel() throws SQLException { + statement.cancel(); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return statement.getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + statement.clearWarnings(); + } + + @Override + public void setCursorName(String name) throws SQLException { + statement.setCursorName(name); + } + + @Override + public boolean execute(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.execute(interceptState.getSql()); + } + + @Override + public ResultSet getResultSet() throws SQLException { + return new ResultSetProxy(statement.getResultSet(), interceptState); + } + + @Override + public int getUpdateCount() throws SQLException { + return statement.getUpdateCount(); + } + + @Override + public boolean getMoreResults() throws SQLException { + return statement.getMoreResults(); + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + statement.setFetchDirection(direction); + } + + @Override + public int getFetchDirection() throws SQLException { + return statement.getFetchDirection(); + } + + @Override + public void setFetchSize(int rows) throws SQLException { + statement.setFetchSize(rows); + } + + @Override + public int getFetchSize() throws SQLException { + return statement.getFetchSize(); + } + + @Override + public int getResultSetConcurrency() throws SQLException { + return statement.getResultSetConcurrency(); + } + + @Override + public int getResultSetType() throws SQLException { + return statement.getResultSetType(); + } + + @Override + public void addBatch(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + statement.addBatch(interceptState.getSql()); + } + + @Override + public void clearBatch() throws SQLException { + statement.clearBatch(); + } + + @Override + public int[] executeBatch() throws SQLException { + return statement.executeBatch(); + } + + @Override + public Connection getConnection() throws SQLException { + return new ConnectionProxy(statement.getConnection()); + } + + @Override + public boolean getMoreResults(int current) throws SQLException { + return statement.getMoreResults(current); + } + + @Override + public ResultSet getGeneratedKeys() throws SQLException { + return new ResultSetProxy(statement.getGeneratedKeys(),this.interceptState); + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.executeUpdate(interceptState.getSql(), autoGeneratedKeys); + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.executeUpdate(interceptState.getSql(), columnIndexes); + } + + @Override + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.executeUpdate(interceptState.getSql(), columnNames); + } + + @Override + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.execute(interceptState.getSql(), autoGeneratedKeys); + } + + @Override + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.execute(interceptState.getSql(), columnIndexes); + } + + @Override + public boolean execute(String sql, String[] columnNames) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.execute(interceptState.getSql(), columnNames); + } + + @Override + public int getResultSetHoldability() throws SQLException { + return statement.getResultSetHoldability(); + } + + @Override + public boolean isClosed() throws SQLException { + return statement.isClosed(); + } + + @Override + public void setPoolable(boolean poolable) throws SQLException { + statement.setPoolable(poolable); + } + + @Override + public boolean isPoolable() throws SQLException { + return statement.isPoolable(); + } + + @Override + public void closeOnCompletion() throws SQLException { + statement.closeOnCompletion(); + } + + @Override + public boolean isCloseOnCompletion() throws SQLException { + return statement.isCloseOnCompletion(); + } + + @Override + public long getLargeUpdateCount() throws SQLException { + return statement.getLargeUpdateCount(); + } + + @Override + public void setLargeMaxRows(long max) throws SQLException { + statement.setLargeMaxRows(max); + } + + @Override + public long getLargeMaxRows() throws SQLException { + return statement.getLargeMaxRows(); + } + + @Override + public long[] executeLargeBatch() throws SQLException { + return statement.executeLargeBatch(); + } + + @Override + public long executeLargeUpdate(String sql) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.executeLargeUpdate(interceptState.getSql()); + } + + @Override + public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.executeLargeUpdate(interceptState.getSql(), autoGeneratedKeys); + } + + @Override + public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.executeLargeUpdate(interceptState.getSql(), columnIndexes); + } + + @Override + public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException { + this.interceptState = SQLRunningContext.getInstance().intercept(sql); + return statement.executeLargeUpdate(interceptState.getSql(), columnNames); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return statement.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return statement.isWrapperFor(iface); + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/ColumnMask.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/ColumnMask.java new file mode 100644 index 00000000..c0721ad0 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/ColumnMask.java @@ -0,0 +1,12 @@ +package com.codingapi.springboot.authorization.mask; + +/** + * 列数据脱敏 + */ +public interface ColumnMask { + + boolean support(Object value); + + Object mask(Object value); + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/ColumnMaskContext.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/ColumnMaskContext.java new file mode 100644 index 00000000..5e84d63a --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/ColumnMaskContext.java @@ -0,0 +1,34 @@ +package com.codingapi.springboot.authorization.mask; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +public class ColumnMaskContext { + + private final List columnMasks; + + private ColumnMaskContext() { + this.columnMasks = new ArrayList<>(); + } + + public void addColumnMask(ColumnMask columnMask) { + this.columnMasks.add(columnMask); + } + + @Getter + private final static ColumnMaskContext instance = new ColumnMaskContext(); + + + public T mask(T value) { + for (ColumnMask columnMask : columnMasks) { + if (columnMask.support(value)) { + return (T)columnMask.mask(value); + } + } + return value; + } + + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/BankCardMask.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/BankCardMask.java new file mode 100644 index 00000000..2aba7e1b --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/BankCardMask.java @@ -0,0 +1,43 @@ +package com.codingapi.springboot.authorization.mask.impl; + +import com.codingapi.springboot.authorization.mask.ColumnMask; + +import java.util.regex.Pattern; + +/** + * 银行卡脱敏 + */ +public class BankCardMask implements ColumnMask { + + private final static Pattern BANK_CARD_MATCHER_PATTERN = Pattern.compile("^\\d{13,19}$"); + private final static Pattern BANK_CARD_MASK_PATTERN = Pattern.compile("(\\d{6})\\d{3,9}(\\d{4})"); + + @Override + public boolean support(Object value) { + if (value instanceof String) { + return BANK_CARD_MATCHER_PATTERN.matcher((String) value).matches(); + } + return false; + } + + @Override + public Object mask(Object value) { + if (value instanceof String) { + String bankCard = (String) value; + int length = bankCard.length(); + // 获取字符串的长度 + int maskLength = length - 10; + + // 手动构造星号部分 + StringBuilder maskedPart = new StringBuilder(maskLength); + for (int i = 0; i < maskLength; i++) { + maskedPart.append("*"); + } + + // 用构造好的星号替换原始字符串中的部分内容 + return BANK_CARD_MASK_PATTERN.matcher((String) value) + .replaceAll("$1" + maskedPart + "$2"); + } + return value; + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/IDCardMask.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/IDCardMask.java new file mode 100644 index 00000000..51541ad9 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/IDCardMask.java @@ -0,0 +1,29 @@ +package com.codingapi.springboot.authorization.mask.impl; + +import com.codingapi.springboot.authorization.mask.ColumnMask; + +import java.util.regex.Pattern; + +/** + * 身份证脱敏 + */ +public class IDCardMask implements ColumnMask { + private final static Pattern ID_CARD_MATCHER_PATTERN = Pattern.compile("^(\\d{15}|\\d{18}|\\d{17}[Xx])$"); + private final static Pattern ID_CARD_MASK_PATTERN = Pattern.compile("(\\d{6})\\d{8}(\\w{4})"); + + @Override + public boolean support(Object value) { + if (value instanceof String) { + return ID_CARD_MATCHER_PATTERN.matcher((String) value).matches(); + } + return false; + } + + @Override + public Object mask(Object value) { + if (value instanceof String) { + return ID_CARD_MASK_PATTERN.matcher( (String) value).replaceAll("$1********$2"); + } + return value; + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/PhoneMask.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/PhoneMask.java new file mode 100644 index 00000000..3903a82f --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/mask/impl/PhoneMask.java @@ -0,0 +1,31 @@ +package com.codingapi.springboot.authorization.mask.impl; + +import com.codingapi.springboot.authorization.mask.ColumnMask; + +import java.util.regex.Pattern; + +/** + * 电话号码脱敏 + */ +public class PhoneMask implements ColumnMask { + + private static final Pattern PHONE_MATCHER_PATTERN = Pattern.compile("^1[3-9]\\d{9}$"); + private static final Pattern PHONE_MASK_PATTERN = Pattern.compile("(\\d{3})\\d{4}(\\d{4})"); + + @Override + public boolean support(Object value) { + if (value instanceof String) { + return PHONE_MATCHER_PATTERN.matcher((String) value).matches(); + } + return false; + } + + @Override + public Object mask(Object value) { + if (value instanceof String) { + return PHONE_MASK_PATTERN.matcher((String) value).replaceAll("$1****$2"); + } + return value; + } + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/properties/DataAuthorizationProperties.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/properties/DataAuthorizationProperties.java new file mode 100644 index 00000000..48bfe771 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/properties/DataAuthorizationProperties.java @@ -0,0 +1,17 @@ +package com.codingapi.springboot.authorization.properties; + + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class DataAuthorizationProperties { + + private boolean showSql = false; + + public DataAuthorizationProperties() { + DataAuthorizationPropertyContext.getInstance().setDataAuthorizationProperties(this); + } + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/properties/DataAuthorizationPropertyContext.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/properties/DataAuthorizationPropertyContext.java new file mode 100644 index 00000000..dcb5f582 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/properties/DataAuthorizationPropertyContext.java @@ -0,0 +1,24 @@ +package com.codingapi.springboot.authorization.properties; + +import lombok.Getter; + +public class DataAuthorizationPropertyContext { + + @Getter + private final static DataAuthorizationPropertyContext instance = new DataAuthorizationPropertyContext(); + + private DataAuthorizationPropertyContext(){} + + private DataAuthorizationProperties dataAuthorizationProperties; + + protected void setDataAuthorizationProperties(DataAuthorizationProperties dataAuthorizationProperties){ + this.dataAuthorizationProperties = dataAuthorizationProperties; + } + + public boolean showSql(){ + if(dataAuthorizationProperties!=null) { + return dataAuthorizationProperties.isShowSql(); + } + return false; + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/ConditionHandlerRegister.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/ConditionHandlerRegister.java new file mode 100644 index 00000000..d39fb34d --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/ConditionHandlerRegister.java @@ -0,0 +1,14 @@ +package com.codingapi.springboot.authorization.register; + + +import com.codingapi.springboot.authorization.handler.RowHandler; +import com.codingapi.springboot.authorization.handler.RowHandlerContext; + +public class ConditionHandlerRegister { + + public ConditionHandlerRegister(RowHandler rowHandler) { + if (rowHandler != null) { + RowHandlerContext.getInstance().setRowHandler(rowHandler); + } + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/DataAuthorizationContextRegister.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/DataAuthorizationContextRegister.java new file mode 100644 index 00000000..39ca7096 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/DataAuthorizationContextRegister.java @@ -0,0 +1,17 @@ +package com.codingapi.springboot.authorization.register; + +import com.codingapi.springboot.authorization.DataAuthorizationContext; +import com.codingapi.springboot.authorization.filter.DataAuthorizationFilter; + +import java.util.List; + +public class DataAuthorizationContextRegister { + + public DataAuthorizationContextRegister(List dataAuthorizationFilters) { + if(dataAuthorizationFilters!=null) { + for (DataAuthorizationFilter filter : dataAuthorizationFilters) { + DataAuthorizationContext.getInstance().addDataAuthorizationFilter(filter); + } + } + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/ResultSetHandlerRegister.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/ResultSetHandlerRegister.java new file mode 100644 index 00000000..6070269a --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/ResultSetHandlerRegister.java @@ -0,0 +1,15 @@ +package com.codingapi.springboot.authorization.register; + + +import com.codingapi.springboot.authorization.handler.ColumnHandler; +import com.codingapi.springboot.authorization.handler.ColumnHandlerContext; + +public class ResultSetHandlerRegister { + + public ResultSetHandlerRegister(ColumnHandler columnHandler){ + if(columnHandler !=null) { + ColumnHandlerContext.getInstance().setColumnHandler(columnHandler); + } + } + +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/SQLInterceptorRegister.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/SQLInterceptorRegister.java new file mode 100644 index 00000000..57534f0d --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/register/SQLInterceptorRegister.java @@ -0,0 +1,14 @@ +package com.codingapi.springboot.authorization.register; + + +import com.codingapi.springboot.authorization.interceptor.SQLInterceptor; +import com.codingapi.springboot.authorization.interceptor.SQLInterceptorContext; + +public class SQLInterceptorRegister { + + public SQLInterceptorRegister(SQLInterceptor sqlInterceptor) { + if(sqlInterceptor!=null) { + SQLInterceptorContext.getInstance().setSqlInterceptor(sqlInterceptor); + } + } +} diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/utils/SQLUtils.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/utils/SQLUtils.java new file mode 100644 index 00000000..817da94c --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/utils/SQLUtils.java @@ -0,0 +1,25 @@ +package com.codingapi.springboot.authorization.utils; + +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.select.Select; + +public class SQLUtils { + + /** + * 判断是否为查询 + */ + public static boolean isQuerySql(String sql) { + if (sql == null || sql.trim().isEmpty()) { + return false; // 空字符串或 null 不是有效 SQL + } + try { + Statement statement = CCJSqlParserUtil.parse(sql); + return statement instanceof Select; + } catch (Exception e) { + return false; + } + } + + +} diff --git a/springboot-starter-data-authorization/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/springboot-starter-data-authorization/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..77aba71d --- /dev/null +++ b/springboot-starter-data-authorization/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.codingapi.springboot.authorization.DataAuthorizationConfiguration diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationContextTest.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationContextTest.java new file mode 100644 index 00000000..3dd25040 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationContextTest.java @@ -0,0 +1,378 @@ +package com.codingapi.springboot.authorization; + +import com.codingapi.springboot.authorization.current.CurrentUser; +import com.codingapi.springboot.authorization.enhancer.DataPermissionSQLEnhancer; +import com.codingapi.springboot.authorization.entity.Depart; +import com.codingapi.springboot.authorization.entity.Unit; +import com.codingapi.springboot.authorization.entity.User; +import com.codingapi.springboot.authorization.filter.DefaultDataAuthorizationFilter; +import com.codingapi.springboot.authorization.handler.Condition; +import com.codingapi.springboot.authorization.handler.RowHandler; +import com.codingapi.springboot.authorization.interceptor.SQLRunningContext; +import com.codingapi.springboot.authorization.mask.ColumnMaskContext; +import com.codingapi.springboot.authorization.mask.impl.BankCardMask; +import com.codingapi.springboot.authorization.mask.impl.IDCardMask; +import com.codingapi.springboot.authorization.mask.impl.PhoneMask; +import com.codingapi.springboot.authorization.repository.DepartRepository; +import com.codingapi.springboot.authorization.repository.UnitRepository; +import com.codingapi.springboot.authorization.repository.UserRepository; +import lombok.extern.slf4j.Slf4j; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.select.SelectItem; +import net.sf.jsqlparser.statement.select.SelectItemVisitor; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.annotation.Rollback; + +import java.time.LocalDate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@Slf4j +@SpringBootTest +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@Rollback(value = false) +public class DataAuthorizationContextTest { + + @Autowired + private UserRepository userRepository; + @Autowired + private DepartRepository departRepository; + @Autowired + private UnitRepository unitRepository; + @Autowired + private JdbcTemplate jdbcTemplate; + + @Test + @Order(1) + void test1() { + + unitRepository.deleteAll(); + departRepository.deleteAll(); + userRepository.deleteAll(); + + + DataAuthorizationContext.getInstance().clearDataAuthorizationFilters(); + + DataAuthorizationContext.getInstance().addDataAuthorizationFilter(new DefaultDataAuthorizationFilter() { + + @Override + public boolean supportRowAuthorization(String tableName, String tableAlias) { + User user = CurrentUser.getInstance().getUser(); + // 模拟仅当用户为lorne时,才进行行级过滤 + return user.getName().equalsIgnoreCase("bob"); + } + + @Override + public Condition rowAuthorization(String tableName, String tableAlias) { + if (tableName.equalsIgnoreCase("t_unit")) { + long unitId = CurrentUser.getInstance().getUser().getUnitId(); + String conditionTemplate = "%s.id = " + unitId; + return Condition.formatCondition(conditionTemplate, tableAlias); + } + if (tableName.equalsIgnoreCase("t_depart")) { + long departId = CurrentUser.getInstance().getUser().getDepartId(); + String conditionTemplate = "%s.id = " + departId; + + // 在条件处理的过程中,执行的查询都将不会被拦截 + List departs = departRepository.findAll(); + log.info("departs:{}", departs); + assertEquals(2, departs.size()); + + return Condition.formatCondition(conditionTemplate, tableAlias); + } + if (tableName.equalsIgnoreCase("t_user")) { + long departId = CurrentUser.getInstance().getUser().getDepartId(); + String conditionTemplate = "%s.depart_id = " + departId; + return Condition.formatCondition(conditionTemplate, tableAlias); + } + return null; + } + + }); + + Unit rootUnit = new Unit("Coding总公司"); + unitRepository.save(rootUnit); + + Unit sdUnit = new Unit("Coding山东分公司", rootUnit.getId()); + unitRepository.save(sdUnit); + + Depart jgbDepart = new Depart("Coding架构部", rootUnit.getId()); + departRepository.save(jgbDepart); + + Depart xmbDepart = new Depart("Coding项目部", sdUnit.getId()); + departRepository.save(xmbDepart); + + + User lorne = new User("lorne", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", jgbDepart); + User bob = new User("bob", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", xmbDepart); + User tom = new User("tom", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", xmbDepart); + + userRepository.save(lorne); + userRepository.save(bob); + userRepository.save(tom); + + + CurrentUser.getInstance().setUser(bob); + + + PageRequest request = PageRequest.of(0, 100); + Page users = userRepository.findAll(request); + + + System.out.println(users.getTotalElements()); + users.forEach(System.out::println); + + + assertEquals(2, users.getTotalElements()); + assertEquals(2, userRepository.count()); + assertEquals(1, departRepository.count()); + assertEquals(1, unitRepository.count()); + + } + + + @Test + @Order(2) + void test2() { + + unitRepository.deleteAll(); + departRepository.deleteAll(); + userRepository.deleteAll(); + + + ColumnMaskContext.getInstance().addColumnMask(new IDCardMask()); + ColumnMaskContext.getInstance().addColumnMask(new PhoneMask()); + ColumnMaskContext.getInstance().addColumnMask(new BankCardMask()); + + DataAuthorizationContext.getInstance().clearDataAuthorizationFilters(); + + DataAuthorizationContext.getInstance().addDataAuthorizationFilter(new DefaultDataAuthorizationFilter() { + @Override + public T columnAuthorization(String tableName, String columnName, T value) { + return ColumnMaskContext.getInstance().mask(value); + } + + @Override + public boolean supportColumnAuthorization(String tableName, String columnName, Object value) { + User user = CurrentUser.getInstance().getUser(); + return user != null && user.getName().equalsIgnoreCase("bob"); + } + + }); + + Unit rootUnit = new Unit("Coding总公司"); + unitRepository.save(rootUnit); + + Unit sdUnit = new Unit("Coding山东分公司", rootUnit.getId()); + unitRepository.save(sdUnit); + + Depart jgbDepart = new Depart("Coding架构部", rootUnit.getId()); + departRepository.save(jgbDepart); + + Depart xmbDepart = new Depart("Coding项目部", sdUnit.getId()); + departRepository.save(xmbDepart); + + + User lorne = new User("lorne", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", jgbDepart); + User bob = new User("bob", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", xmbDepart); + User tom = new User("tom", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", xmbDepart); + + userRepository.save(lorne); + userRepository.save(bob); + userRepository.save(tom); + + assertTrue(SQLRunningContext.getInstance().skipDataAuthorization(() -> userRepository.findAll()).size() >= 3); + + CurrentUser.getInstance().setUser(bob); + + PageRequest request = PageRequest.of(0, 100); + Page users = userRepository.findAll(request); + assertTrue(users.getTotalElements() >= 3); + + for (User user : users) { + assertEquals("138****5678", user.getPhone()); + } + + CurrentUser.getInstance().setUser(lorne); + + users = userRepository.findAll(request); + assertTrue(users.getTotalElements() >= 3); + + for (User user : users) { + assertEquals("13812345678", user.getPhone()); + } + + + } + + + @Test + @Order(3) + void test3() { + + unitRepository.deleteAll(); + departRepository.deleteAll(); + userRepository.deleteAll(); + + ColumnMaskContext.getInstance().addColumnMask(new IDCardMask()); + ColumnMaskContext.getInstance().addColumnMask(new PhoneMask()); + ColumnMaskContext.getInstance().addColumnMask(new BankCardMask()); + + DataAuthorizationContext.getInstance().clearDataAuthorizationFilters(); + + DataAuthorizationContext.getInstance().addDataAuthorizationFilter(new DefaultDataAuthorizationFilter() { + @Override + public T columnAuthorization(String tableName, String columnName, T value) { + return ColumnMaskContext.getInstance().mask(value); + } + + @Override + public boolean supportColumnAuthorization(String tableName, String columnName, Object value) { + return true; + } + + }); + + Unit rootUnit = new Unit("Coding总公司"); + unitRepository.save(rootUnit); + + Unit sdUnit = new Unit("Coding山东分公司", rootUnit.getId()); + unitRepository.save(sdUnit); + + Depart jgbDepart = new Depart("Coding架构部", rootUnit.getId()); + departRepository.save(jgbDepart); + + Depart xmbDepart = new Depart("Coding项目部", sdUnit.getId()); + departRepository.save(xmbDepart); + + User lorne = new User("lorne", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", jgbDepart); + User bob = new User("bob", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", xmbDepart); + User tom = new User("tom", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", xmbDepart); + + userRepository.save(lorne); + userRepository.save(bob); + userRepository.save(tom); + + List> users = jdbcTemplate.queryForList("select * from t_user"); + System.out.println(users); + assertEquals(3, users.size()); + + for (Map user : users) { + assertEquals("138****5678", user.get("phone")); + } + + } + + +// @Test + @Order(4) + void test4() throws Exception{ + String sql = "SELECT\n" + + "\tt.* \n" + + "FROM\n" + + "\t(\n" + + "\t\tSELECT\n" + + "\t\t\tUNYiV.id AS '历史工作经历编号',\n" + + "\t\t\tUNYiV.company_name AS '历史工作单位',\n" + + "\t\t\tUNYiV.depart_name AS '历史工作部门',\n" + + "\t\t\tUNYiV.post_name AS '历史工作岗位',\n" + + "\t\t\tUNYiV.start_date AS '开始时间',\n" + + "\t\t\tUNYiV.end_date AS '结束时间',\n" + + "\t\t\towasH.员工编号 AS '员工编号',\n" + + "\t\t\towasH.员工姓名 AS '员工姓名',\n" + + "\t\t\towasH.员工生日 AS '员工生日',\n" + + "\t\t\towasH.员工地址 AS '员工地址',\n" + + "\t\t\towasH.身份证号码 AS '身份证号码',\n" + + "\t\t\towasH.手机号 AS '手机号',\n" + + "\t\t\towasH.部门编号 AS '部门编号',\n" + + "\t\t\towasH.岗位编号 AS '岗位编号',\n" + + "\t\t\towasH.任现职编号 AS '任现职编号',\n" + + "\t\t\towasH.社团编号 AS '社团编号',\n" + + "\t\t\towasH.社团名称 AS '社团名称',\n" + + "\t\t\towasH.创建时间 AS '创建时间' \n" + + "\t\tFROM\n" + + "\t\t\tt_work AS pehMS,\n" + + "\t\t\tt_employee AS OGwG7,\n" + + "\t\t\tt_work_history AS UNYiV,\n" + + "\t\t\t(\n" + + "\t\t\t\tSELECT\n" + + "\t\t\t\t\tWXJj8.id AS '员工编号',\n" + + "\t\t\t\t\tWXJj8.NAME AS '员工姓名',\n" + + "\t\t\t\t\tWXJj8.birth_date AS '员工生日',\n" + + "\t\t\t\t\tWXJj8.address AS '员工地址',\n" + + "\t\t\t\t\tWXJj8.id_card AS '身份证号码',\n" + + "\t\t\t\t\tWXJj8.phone AS '手机号',\n" + + "\t\t\t\t\tWXJj8.depart_id AS '部门编号',\n" + + "\t\t\t\t\tWXJj8.post_id AS '岗位编号',\n" + + "\t\t\t\t\tWXJj8.work_id AS '任现职编号',\n" + + "\t\t\t\t\trnGD4.id AS '社团编号',\n" + + "\t\t\t\t\trnGD4.NAME AS '社团名称',\n" + + "\t\t\t\t\trnGD4.create_date AS '创建时间' \n" + + "\t\t\t\tFROM\n" + + "\t\t\t\t\tt_employee AS WXJj8,\n" + + "\t\t\t\t\tt_league_employee AS dEj96,\n" + + "\t\t\t\t\tt_league AS rnGD4 \n" + + "\t\t\t\tWHERE\n" + + "\t\t\t\t\trnGD4.id < 100 \n" + + "\t\t\t\t\tAND dEj96.employee_id = WXJj8.id \n" + + "\t\t\t\t\tAND dEj96.league_id = rnGD4.id \n" + + "\t\t\t\t\tAND 1 = 1 \n" + + "\t\t\t) AS owasH \n" + + "\t\tWHERE\n" + + "\t\t\tUNYiV.employee_id = OGwG7.id \n" + + "\t\t\tAND OGwG7.work_id = pehMS.id \n" + + "\t\t\tAND owasH.任现职编号 = pehMS.id \n" + + "\t\t\tAND 1 = 1 \n" + + "\t) AS t , t_employee AS e where t.员工编号 = e.id and e.id = 1"; + + + DataAuthorizationContext.getInstance().clearDataAuthorizationFilters(); + DataAuthorizationContext.getInstance().addDataAuthorizationFilter(new DefaultDataAuthorizationFilter() { + @Override + public Condition rowAuthorization(String tableName, String tableAlias) { + return super.rowAuthorization(tableName, tableAlias); + } + + @Override + public T columnAuthorization(String tableName, String columnName, T value) { + System.out.println("tableName:" + tableName + ",columnName:" + columnName + ",value:" + value); + return value; + } + + @Override + public boolean supportColumnAuthorization(String tableName, String columnName, Object value) { + return true; + } + + @Override + public boolean supportRowAuthorization(String tableName, String tableAlias) { + return true; + } + }); + + + List> data = jdbcTemplate.queryForList(sql); +// System.out.println(data); + } + + + + +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationTestApplication.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationTestApplication.java new file mode 100644 index 00000000..0760ec6a --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationTestApplication.java @@ -0,0 +1,13 @@ +package com.codingapi.springboot.authorization; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DataAuthorizationTestApplication { + + public static void main(String[] args) { + SpringApplication.run(DataAuthorizationConfiguration.class,args); + } + +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/analyzer/SelectSQLAnalyzerTest.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/analyzer/SelectSQLAnalyzerTest.java new file mode 100644 index 00000000..ce2309f6 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/analyzer/SelectSQLAnalyzerTest.java @@ -0,0 +1,198 @@ +package com.codingapi.springboot.authorization.analyzer; + +import com.codingapi.springboot.authorization.enhancer.DataPermissionSQLEnhancer; +import com.codingapi.springboot.authorization.handler.Condition; +import com.codingapi.springboot.authorization.handler.RowHandler; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; + +import java.sql.SQLException; + +import static org.junit.jupiter.api.Assertions.*; + +class SelectSQLAnalyzerTest { + + + @Test + void test1() throws SQLException { + String sql = "select t1.*,t2.* from (SELECT * FROM t_employee as a2 WHERE id = 100 ) t1 ," + + " (SELECT * FROM t_employee as a1 ) t2 ," + + " (select * from t_employee a3 left join t_unit u on a3.unit_id = u.id ) t3 ," + + " (select 1 =1 ) as t4 " + + " limit 100"; + + RowHandler rowHandler = (subSql, tableName, tableAlias) -> { + if (tableName.equalsIgnoreCase("t_employee")) { + String conditionTemplate = "%s.id > 100 "; + return Condition.formatCondition(conditionTemplate, tableAlias); + } + return null; + }; + + DataPermissionSQLEnhancer builder = new DataPermissionSQLEnhancer(sql, rowHandler); + String newSql = builder.getNewSQL(); + System.out.println(newSql); + //SELECT t1.*, t2.* FROM (SELECT * FROM t_employee AS a2 WHERE a2.id > 100 AND id = 100) t1, + // (SELECT * FROM t_employee AS a1 WHERE a1.id > 100) t2, + // (SELECT * FROM t_employee a3 LEFT JOIN t_unit u ON a3.unit_id = u.id WHERE a3.id > 100) t3, + // (SELECT 1 = 1) AS t4 LIMIT 100 + assertEquals( + "SELECT t1.*, t2.* FROM (SELECT * FROM t_employee AS a2 WHERE a2.id > 100 AND id = 100) t1," + + " (SELECT * FROM t_employee AS a1 WHERE a1.id > 100) t2, " + + "(SELECT * FROM t_employee a3 LEFT JOIN t_unit u ON a3.unit_id = u.id WHERE a3.id > 100) t3, " + + "(SELECT 1 = 1) AS t4 LIMIT 100", newSql); + } + + @Test + void test2() throws SQLException { + String sql = "select e1_0.id,e1_0.address,e1_0.birth_date,e1_0.depart_id,e1_0.id_card,e1_0.name,e1_0.phone,e1_0.post_id,e1_0.work_id from t_employee e1_0 limit ?,?"; + + RowHandler rowHandler = (subSql, tableName, tableAlias) -> { + if (tableName.equalsIgnoreCase("t_employee")) { + String conditionTemplate = "%s.id > 100 "; + return Condition.formatCondition(conditionTemplate, tableAlias); + } + return null; + }; + + DataPermissionSQLEnhancer builder = new DataPermissionSQLEnhancer(sql, rowHandler); + String newSql = builder.getNewSQL(); + System.out.println(newSql); + assertEquals("SELECT e1_0.id, e1_0.address, e1_0.birth_date, e1_0.depart_id, e1_0.id_card, e1_0.name, e1_0.phone, e1_0.post_id, e1_0.work_id FROM t_employee e1_0 WHERE e1_0.id > 100 LIMIT ?, ?", newSql); } + + + @Test + void test3() throws SQLException { + String sql = "select aue1_0.ba_org_code from ba03_administrative_unit aue1_0 where aue1_0.ba_org_code like (?||'__') order by aue1_0.ba_org_code desc"; + + RowHandler rowHandler = (subSql, tableName, tableAlias) -> { + if (tableName.equalsIgnoreCase("ba03_administrative_unit")) { + String conditionTemplate = "%s.id > 100 "; + return Condition.formatCondition(conditionTemplate, tableAlias); + } + return null; + }; + + DataPermissionSQLEnhancer builder = new DataPermissionSQLEnhancer(sql, rowHandler); + String newSql = builder.getNewSQL(); + System.out.println(newSql); + assertEquals("SELECT aue1_0.ba_org_code FROM ba03_administrative_unit aue1_0 WHERE aue1_0.id > 100 AND aue1_0.ba_org_code LIKE (? || '__') ORDER BY aue1_0.ba_org_code DESC", newSql); + } + + @Test + void test4() throws SQLException{ + String sql = "SELECT\n" + + "\tUNYiV.id AS '历史工作经历编号',\n" + + "\tUNYiV.company_name AS '历史工作单位',\n" + + "\tUNYiV.depart_name AS '历史工作部门',\n" + + "\tUNYiV.post_name AS '历史工作岗位',\n" + + "\tUNYiV.start_date AS '开始时间',\n" + + "\tUNYiV.end_date AS '结束时间',\n" + + "\towasH.员工编号 AS '员工编号',\n" + + "\towasH.员工姓名 AS '员工姓名',\n" + + "\towasH.员工生日 AS '员工生日',\n" + + "\towasH.员工地址 AS '员工地址',\n" + + "\towasH.身份证号码 AS '身份证号码',\n" + + "\towasH.手机号 AS '手机号',\n" + + "\towasH.部门编号 AS '部门编号',\n" + + "\towasH.岗位编号 AS '岗位编号',\n" + + "\towasH.任现职编号 AS '任现职编号',\n" + + "\towasH.社团编号 AS '社团编号',\n" + + "\towasH.社团名称 AS '社团名称',\n" + + "\towasH.创建时间 AS '创建时间' \n" + + "FROM\n" + + "\tt_work AS pehMS,\n" + + "\tt_employee AS OGwG7,\n" + + "\tt_work_history AS UNYiV,\n" + + "\t(\n" + + "\t\tSELECT\n" + + "\t\t\tWXJj8.id AS '员工编号',\n" + + "\t\t\tWXJj8.NAME AS '员工姓名',\n" + + "\t\t\tWXJj8.birth_date AS '员工生日',\n" + + "\t\t\tWXJj8.address AS '员工地址',\n" + + "\t\t\tWXJj8.id_card AS '身份证号码',\n" + + "\t\t\tWXJj8.phone AS '手机号',\n" + + "\t\t\tWXJj8.depart_id AS '部门编号',\n" + + "\t\t\tWXJj8.post_id AS '岗位编号',\n" + + "\t\t\tWXJj8.work_id AS '任现职编号',\n" + + "\t\t\trnGD4.id AS '社团编号',\n" + + "\t\t\trnGD4.NAME AS '社团名称',\n" + + "\t\t\trnGD4.create_date AS '创建时间' \n" + + "\t\tFROM\n" + + "\t\t\tt_employee AS WXJj8,\n" + + "\t\t\tt_league_employee AS dEj96,\n" + + "\t\t\tt_league AS rnGD4 \n" + + "\t\tWHERE\n" + + "\t\t\tdEj96.employee_id = WXJj8.id \n" + + "\t\t\tAND dEj96.league_id = rnGD4.id \n" + + "\t\t\tAND 1 = 1 \n" + + "\t) AS owasH \n" + + "WHERE\n" + + "\tUNYiV.employee_id = OGwG7.id \n" + + "\tAND OGwG7.work_id = pehMS.id \n" + + "\tAND owasH.任现职编号 = pehMS.id \n" + + "\tAND 1 = 1"; + + + RowHandler rowHandler = (subSql, tableName, tableAlias) -> { + if (tableName.equalsIgnoreCase("t_league")) { + String conditionTemplate = "%s.id < 100 "; + return Condition.formatCondition(conditionTemplate, tableAlias); + } + return null; + }; + + DataPermissionSQLEnhancer builder = new DataPermissionSQLEnhancer(sql, rowHandler); + System.out.println(builder.getNewSQL()); + System.out.println(builder.getTableAlias());; + } + + @Test + @Order(5) + void test5() throws Exception{ + String sql = "SELECT next_val AS id_val FROM t_league_seq FOR UPDATE"; + RowHandler rowHandler = (subSql, tableName, tableAlias) -> { + if (tableName.equalsIgnoreCase("t_league")) { + String conditionTemplate = "%s.id < 100 "; + return Condition.formatCondition(conditionTemplate, tableAlias); + } + return null; + }; + DataPermissionSQLEnhancer builder = new DataPermissionSQLEnhancer(sql, rowHandler); + System.out.println(builder.getNewSQL()); + System.out.println(builder.getTableAlias());; + } + + + @Test + @Order(6) + void test6() throws Exception{ + String sql = "SELECT 1=1"; + RowHandler rowHandler = (subSql, tableName, tableAlias) -> { + if (tableName.equalsIgnoreCase("t_league")) { + String conditionTemplate = "%s.id < 100 "; + return Condition.formatCondition(conditionTemplate, tableAlias); + } + return null; + }; + DataPermissionSQLEnhancer builder = new DataPermissionSQLEnhancer(sql, rowHandler); + System.out.println(builder.getNewSQL()); + System.out.println(builder.getTableAlias());; + } + + @Test + @Order(7) + void test7() throws Exception{ + String sql = "SELECT * from t_employee"; + RowHandler rowHandler = (subSql, tableName, tableAlias) -> { + if (tableName.equalsIgnoreCase("t_employee")) { + String conditionTemplate = "%s.id < 100 "; + return Condition.formatCondition(conditionTemplate, tableAlias); + } + return null; + }; + DataPermissionSQLEnhancer builder = new DataPermissionSQLEnhancer(sql, rowHandler); + System.out.println(builder.getNewSQL()); + System.out.println(builder.getTableAlias());; + } +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/current/CurrentUser.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/current/CurrentUser.java new file mode 100644 index 00000000..186c3d00 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/current/CurrentUser.java @@ -0,0 +1,27 @@ +package com.codingapi.springboot.authorization.current; + +import com.codingapi.springboot.authorization.entity.User; +import lombok.Getter; + +public class CurrentUser { + + @Getter + private final static CurrentUser instance = new CurrentUser(); + + private final ThreadLocal threadLocal = new ThreadLocal<>(); + + private CurrentUser(){ + } + + public void setUser(User user){ + threadLocal.set(user); + } + + public User getUser(){ + return threadLocal.get(); + } + + public void remove(){ + threadLocal.remove(); + } +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/Depart.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/Depart.java new file mode 100644 index 00000000..865d8801 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/Depart.java @@ -0,0 +1,38 @@ +package com.codingapi.springboot.authorization.entity; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +@Setter +@Getter +@Entity +@Table(name = "t_depart") +@NoArgsConstructor +public class Depart { + + @Id + @GeneratedValue + private long id; + + private String name; + + private long parentId; + + private long unitId; + + public Depart(String name, long unitId,long parentId) { + this.name = name; + this.parentId = parentId; + this.unitId = unitId; + } + + public Depart(String name,long unitId) { + this(name,unitId,0); + } +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/Unit.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/Unit.java new file mode 100644 index 00000000..4ea4b0a7 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/Unit.java @@ -0,0 +1,34 @@ +package com.codingapi.springboot.authorization.entity; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Setter +@Getter +@Entity +@Table(name = "t_unit") +@NoArgsConstructor +public class Unit { + + @Id + @GeneratedValue + private long id; + + private String name; + + private long parentId; + + public Unit(String name, long parentId) { + this.name = name; + this.parentId = parentId; + } + + public Unit(String name) { + this(name,0); + } +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/User.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/User.java new file mode 100644 index 00000000..04fca1f3 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/entity/User.java @@ -0,0 +1,49 @@ +package com.codingapi.springboot.authorization.entity; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.time.LocalDate; + +@Setter +@Getter +@Entity +@Table(name = "t_user") +@NoArgsConstructor +@ToString +public class User { + + @Id + @GeneratedValue + private long id; + + private String name; + + private LocalDate birthDate; + + private String address; + + private String idCard; + + private String phone; + + private long unitId; + + private long departId; + + public User(String name, LocalDate birthDate, String address, String idCard, String phone,Depart depart) { + this.name = name; + this.birthDate = birthDate; + this.address = address; + this.idCard = idCard; + this.phone = phone; + this.unitId = depart.getUnitId(); + this.departId = depart.getId(); + } +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/BankCardMaskTest.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/BankCardMaskTest.java new file mode 100644 index 00000000..0b75e2e4 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/BankCardMaskTest.java @@ -0,0 +1,17 @@ +package com.codingapi.springboot.authorization.mask.impl; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class BankCardMaskTest { + + @Test + void test() { + String bankCard = "6222021001111111111"; + BankCardMask mask = new BankCardMask(); + assertTrue(mask.support(bankCard)); + assertEquals("622202*********1111", mask.mask(bankCard)); + } +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/IDCardMaskTest.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/IDCardMaskTest.java new file mode 100644 index 00000000..3e758452 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/IDCardMaskTest.java @@ -0,0 +1,16 @@ +package com.codingapi.springboot.authorization.mask.impl; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class IDCardMaskTest { + + @Test + void test(){ + String idCard = "110101199003074012"; + IDCardMask mask = new IDCardMask(); + assertTrue(mask.support(idCard)); + assertEquals("110101********4012", mask.mask(idCard)); + } +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/PhoneMaskTest.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/PhoneMaskTest.java new file mode 100644 index 00000000..d5c8d4f5 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/mask/impl/PhoneMaskTest.java @@ -0,0 +1,17 @@ +package com.codingapi.springboot.authorization.mask.impl; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class PhoneMaskTest { + + @Test + void test(){ + String phone = "15562581234"; + PhoneMask phoneMask = new PhoneMask(); + assertTrue(phoneMask.support(phone)); + assertEquals("155****1234", phoneMask.mask(phone)); + } + +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/DepartRepository.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/DepartRepository.java new file mode 100644 index 00000000..b9c00b84 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/DepartRepository.java @@ -0,0 +1,8 @@ +package com.codingapi.springboot.authorization.repository; + +import com.codingapi.springboot.authorization.entity.Depart; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface DepartRepository extends JpaRepository { + +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/UnitRepository.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/UnitRepository.java new file mode 100644 index 00000000..0bc6416d --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/UnitRepository.java @@ -0,0 +1,8 @@ +package com.codingapi.springboot.authorization.repository; + +import com.codingapi.springboot.authorization.entity.Unit; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UnitRepository extends JpaRepository { + +} diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/UserRepository.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/UserRepository.java new file mode 100644 index 00000000..f36df247 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/repository/UserRepository.java @@ -0,0 +1,12 @@ +package com.codingapi.springboot.authorization.repository; + +import com.codingapi.springboot.authorization.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface UserRepository extends JpaRepository { + + + List findUserByDepartId(long departId); +} diff --git a/springboot-starter-data-authorization/src/test/resources/application.properties b/springboot-starter-data-authorization/src/test/resources/application.properties new file mode 100644 index 00000000..4e944839 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/resources/application.properties @@ -0,0 +1,13 @@ + +spring.datasource.driver-class-name=com.codingapi.springboot.authorization.jdbc.AuthorizationJdbcDriver +spring.datasource.url=jdbc:h2:file:./test.db +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.show-sql=true + +#spring.datasource.driver-class-name=com.codingapi.springboot.authorization.jdbc.AuthorizationJdbcDriver +#spring.datasource.url=jdbc:mysql://localhost:3306/example?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true +#spring.datasource.username=root +#spring.datasource.password=lorne4j#2024 + +logging.level.com.codingapi.springboot.authorization=debug diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 8d142d1e..654d2dd8 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.14 + 2.9.15 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index b5fadf19..3255022e 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.14 + 2.9.15 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 0357b2d4..0b2c8a84 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.14 + 2.9.15 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index d8c0d844..afc5c315 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.14 + 2.9.15 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 23fb5d83..1c514784 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.14 +CodingApi SpringBoot-Starter 2.9.15 springboot version (${spring-boot.version}) ------------------------------------------------------ From ac787c144acb22193bf58c3b0864db39bd99111d Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 23 Dec 2024 12:00:12 +0800 Subject: [PATCH 074/129] fix reject back operator --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../flow/service/FlowNodeService.java | 14 +- .../springboot/flow/test/SignTest.java | 136 ++++++++++++++---- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 9 files changed, 126 insertions(+), 38 deletions(-) diff --git a/pom.xml b/pom.xml index 3ac27491..577ce5de 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.15 + 2.9.16 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 4be50638..68351e5c 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.15 + 2.9.16 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 654d2dd8..aa4522a0 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.15 + 2.9.16 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 3255022e..ecdd7f60 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.15 + 2.9.16 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java index b7210a8d..4d3a092f 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java @@ -18,6 +18,7 @@ import lombok.Getter; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -29,6 +30,7 @@ public class FlowNodeService { @Getter private FlowNode nextNode; private IFlowOperator nextOperator; + private IFlowOperator backOperator; private final FlowOperatorRepository flowOperatorRepository; private final FlowRecordRepository flowRecordRepository; @@ -116,6 +118,7 @@ public void loadDefaultBackNode(long parentRecordId) { } this.nextNode = nextNode; this.nextOperator = flowOperator; + this.backOperator = flowOperator; } @@ -138,6 +141,7 @@ public void loadCustomBackNode(FlowNode flowNode, long parentRecordId) { } this.nextNode = nextNode; this.nextOperator = flowOperator; + this.backOperator = flowOperator; } @@ -239,10 +243,16 @@ private List createNextRecord() { historyRecords); long workId = flowWork.getId(); - List operators = nextNode.loadFlowNodeOperator(flowSession, flowOperatorRepository); + List operators = null; + if (this.backOperator == null) { + operators = nextNode.loadFlowNodeOperator(flowSession, flowOperatorRepository); + } else { + operators = Collections.singletonList(this.backOperator); + } List customOperatorIds = opinion.getOperatorIds(); if (customOperatorIds != null && !customOperatorIds.isEmpty()) { - operators = operators.stream().filter(operator -> customOperatorIds.contains(operator.getUserId())).collect(Collectors.toList()); + operators = operators.stream() + .filter(operator -> customOperatorIds.contains(operator.getUserId())).collect(Collectors.toList()); if (operators.size() != customOperatorIds.size()) { throw new IllegalArgumentException("operator not match."); } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java index c4073ceb..6c47cf15 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java @@ -124,6 +124,113 @@ void unSignTest(){ } + /** + * 多人非会签拒绝测试 + */ + @Test + void unSignRejectTest(){ + PageRequest pageRequest = PageRequest.of(0, 1000); + + User caocao = new User("曹操"); + userRepository.save(caocao); + User lvBu = new User("吕布"); + userRepository.save(lvBu); + User zhaoYun = new User("赵云"); + userRepository.save(zhaoYun); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, + OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),caocao.getUserId(),lvBu.getUserId(),zhaoYun.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(lvBu.getUserId())); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + // 查看部门刘备经理的待办 + List lvBuTodos = flowRecordRepository.findTodoByOperatorId(lvBu.getUserId(), pageRequest).getContent(); + assertEquals(1, lvBuTodos.size()); + + // 提交部门经理的审批 + FlowRecord lvBuTodo = lvBuTodos.get(0); + flowService.submitFlow(lvBuTodo.getId(), lvBu, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.reject("不同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent();; + assertEquals(4, records.size()); + + lvBuTodos = flowRecordRepository.findTodoByOperatorId(lvBu.getUserId(), pageRequest).getContent(); + assertEquals(1, lvBuTodos.size()); + + // 提交部门经理的审批 + lvBuTodo = lvBuTodos.get(0); + flowService.submitFlow(lvBuTodo.getId(), lvBu, leave, Opinion.pass("同意")); + + + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("行吧")); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(6, snapshots.size()); + + } + /** * 多人会签测试 @@ -495,35 +602,6 @@ void signTrySubmitTest(){ List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); assertEquals(1, bossTodos.size()); -// // 查看部门经理 吕布 的待办 -// List lvbuTodos = flowRecordRepository.findTodoByOperatorId(lvBu.getUserId(), pageRequest).getContent(); -// assertEquals(1, lvbuTodos.size()); -// -// // 提交部门经理 吕布 的审批 -// FlowRecord lvbuTodo = lvbuTodos.get(0); -// flowService.submitFlow(lvbuTodo.getId(), lvBu, leave, Opinion.pass("吕布同意")); -// -// -// // 查看部门经理 赵云 的待办 -// List zhaoYunTodos = flowRecordRepository.findTodoByOperatorId(zhaoYun.getUserId(), pageRequest).getContent(); -// assertEquals(1, zhaoYunTodos.size()); -// -// // 提交部门经理 赵云 的审批 -// FlowRecord zhaoYunTodo = zhaoYunTodos.get(0); -// flowService.submitFlow(zhaoYunTodo.getId(), zhaoYun, leave, Opinion.pass("赵云同意")); -// -// -// // 查看部门经理 曹操 的待办 -// List caocaoTodos = flowRecordRepository.findTodoByOperatorId(caocao.getUserId(), pageRequest).getContent(); -// assertEquals(1, caocaoTodos.size()); -// -// // 提交部门经理 曹操 的审批 -// FlowRecord caocaoTodo = caocaoTodos.get(0); -// flowService.submitFlow(caocaoTodo.getId(), caocao, leave, Opinion.pass("曹操同意")); -// -// bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); -// assertEquals(1, bossTodos.size()); - // 提交总经理的审批 FlowRecord bossTodo = bossTodos.get(0); flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 0b2c8a84..8306aaa3 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.15 + 2.9.16 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index afc5c315..4e33f654 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.15 + 2.9.16 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 1c514784..3c735191 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.15 +CodingApi SpringBoot-Starter 2.9.16 springboot version (${spring-boot.version}) ------------------------------------------------------ From 4c663c3e5c73f81dbf88f21a9b8bb8c66c2089f1 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 2 Jan 2025 14:25:29 +0800 Subject: [PATCH 075/129] update 2.9.17 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../flow/build/FlowWorkBuilder.java | 5 + .../springboot/flow/domain/FlowWork.java | 8 + .../springboot/flow/pojo/FlowResult.java | 12 + .../serializable/FlowWorkSerializable.java | 8 + .../flow/service/FlowRecordVerifyService.java | 91 +++-- .../springboot/flow/service/FlowService.java | 33 +- .../service/FlowServiceRepositoryHolder.java | 29 ++ .../service/impl/FlowCustomEventService.java | 6 +- .../flow/service/impl/FlowDetailService.java | 3 +- .../service/impl/FlowPostponedService.java | 5 +- .../flow/service/impl/FlowRecallService.java | 7 +- .../flow/service/impl/FlowSaveService.java | 6 +- .../flow/service/impl/FlowStartService.java | 185 ++++++--- .../flow/service/impl/FlowSubmitService.java | 354 +++++++++++++----- .../service/impl/FlowTransferService.java | 5 +- .../service/impl/FlowTrySubmitService.java | 258 ++----------- .../flow/service/impl/FlowUrgeService.java | 7 +- .../springboot/flow/test/FlowTest.java | 77 ++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 25 files changed, 672 insertions(+), 441 deletions(-) create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowServiceRepositoryHolder.java diff --git a/pom.xml b/pom.xml index 577ce5de..bfc27db6 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.16 + 2.9.17 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 68351e5c..39c26c89 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.16 + 2.9.17 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index aa4522a0..07a6998e 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.16 + 2.9.17 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index ecdd7f60..40335d3a 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.16 + 2.9.17 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java index 2749b7cf..b9908f14 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java @@ -41,6 +41,11 @@ public FlowWorkBuilder postponedMax(int postponedMax) { return this; } + public FlowWorkBuilder skipIfSameApprover(boolean skipIfSameApprover) { + this.work.setSkipIfSameApprover(skipIfSameApprover); + return this; + } + public FlowWorkBuilder title(String title) { this.work.setTitle(title); return this; diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java index ffb91d08..b6ad791a 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java @@ -60,6 +60,12 @@ public class FlowWork { */ private boolean enable; + /** + * 是否跳过相同审批人,默认为false + */ + @Setter + private boolean skipIfSameApprover; + /** * 最大延期次数 */ @@ -122,6 +128,7 @@ public FlowWork copy(){ flowWork.setTitle(this.getTitle()); flowWork.setCode(RandomGenerator.randomString(8)); flowWork.setPostponedMax(this.getPostponedMax()); + flowWork.setSkipIfSameApprover(this.isSkipIfSameApprover()); flowWork.schema(schema); return flowWork; } @@ -225,6 +232,7 @@ public FlowWorkSerializable toSerializable() { createUser.getUserId(), createTime, updateTime, + skipIfSameApprover, enable, postponedMax, schema, diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java index 4e16e495..ad65b649 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java @@ -2,10 +2,12 @@ import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.user.IFlowOperator; import lombok.Getter; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @Getter public class FlowResult { @@ -23,4 +25,14 @@ public FlowResult(FlowWork flowWork,FlowRecord flowRecord) { this.records = new ArrayList<>(); this.records.add(flowRecord); } + + + /** + * 匹配操作者的记录 + * @param operator 操作者 + * @return 记录 + */ + public List matchRecordByOperator(IFlowOperator operator){ + return records.stream().filter(record -> record.isOperator(operator)).collect(Collectors.toList()); + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java index 1903d63d..d25d039a 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java @@ -63,6 +63,13 @@ public class FlowWorkSerializable implements Serializable { * 更新时间 */ private long updateTime; + + /** + * 是否跳过相同审批人,默认为false + */ + @Setter + private boolean skipIfSameApprover; + /** * 是否启用 */ @@ -140,6 +147,7 @@ public FlowWork toFlowWork(FlowOperatorRepository flowOperatorRepository) { createTime, updateTime, enable, + skipIfSameApprover, postponedMax, flowNodes, relations.stream().map((item) -> item.toFlowRelation(flowNodes)).collect(Collectors.toList()), diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java index b923f10b..003db90c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java @@ -5,6 +5,7 @@ import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.FlowProcessRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; import com.codingapi.springboot.flow.user.IFlowOperator; import lombok.Getter; @@ -16,13 +17,13 @@ public class FlowRecordVerifyService { // constructor params - private final long recordId; @Getter private final IFlowOperator currentOperator; // register repository final FlowRecordRepository flowRecordRepository; final FlowProcessRepository flowProcessRepository; + final FlowWorkRepository flowWorkRepository; // load Object @Getter @@ -30,23 +31,44 @@ public class FlowRecordVerifyService { @Getter private FlowNode flowNode; @Getter - private FlowRecord flowRecord; + private final FlowRecord flowRecord; + + public FlowRecordVerifyService( + FlowWorkRepository flowWorkRepository, + FlowRecordRepository flowRecordRepository, + FlowProcessRepository flowProcessRepository, + long recordId, + IFlowOperator currentOperator) { + this.flowWorkRepository = flowWorkRepository; + this.flowRecordRepository = flowRecordRepository; + this.flowProcessRepository = flowProcessRepository; - public FlowRecordVerifyService(FlowRecordRepository flowRecordRepository, + this.currentOperator = currentOperator; + FlowRecord flowRecord = flowRecordRepository.getFlowRecordById(recordId); + if (flowRecord == null) { + throw new IllegalArgumentException("flow record not found"); + } + this.flowRecord = flowRecord; + } + + public FlowRecordVerifyService(FlowWorkRepository flowWorkRepository, + FlowRecordRepository flowRecordRepository, FlowProcessRepository flowProcessRepository, - long recordId, + FlowRecord flowRecord, + FlowWork flowWork, IFlowOperator currentOperator) { + this.flowWorkRepository = flowWorkRepository; this.flowRecordRepository = flowRecordRepository; this.flowProcessRepository = flowProcessRepository; this.currentOperator = currentOperator; - this.recordId = recordId; + this.flowRecord = flowRecord; + this.flowWork = flowWork; } - /** - * 校验流程记录是否已提交状态 + * 校验流程记录是否已提交状态 */ public void verifyFlowRecordSubmitState() { flowRecord.submitStateVerify(); @@ -56,13 +78,13 @@ public void verifyFlowRecordSubmitState() { * 校验流程是否当前操作者可操作的 */ public void verifyFlowRecordCurrentOperator() { - if(!currentOperator.isFlowManager()) { + if (!currentOperator.isFlowManager()) { flowRecord.matcherOperator(currentOperator); } } /** - * 校验流程是否已审批 + * 校验流程是否已审批 */ public void verifyFlowRecordNotDone() { if (flowRecord.isDone()) { @@ -72,7 +94,7 @@ public void verifyFlowRecordNotDone() { /** - * 校验流程是否已审批 + * 校验流程是否已审批 */ public void verifyFlowRecordIsDone() { if (!flowRecord.isDone()) { @@ -81,20 +103,19 @@ public void verifyFlowRecordIsDone() { } - /** - * 校验流程是否未审批 + * 校验流程是否未审批 */ public void verifyFlowRecordNotTodo() { if (flowRecord.isTodo()) { - if(!flowRecord.isStartRecord()) { + if (!flowRecord.isStartRecord()) { throw new IllegalArgumentException("flow record is todo"); } } } /** - * 校验流程是未审批 + * 校验流程是未审批 */ public void verifyFlowRecordIsTodo() { if (!flowRecord.isTodo()) { @@ -103,7 +124,7 @@ public void verifyFlowRecordIsTodo() { } /** - * 校验流程是否已完成 + * 校验流程是否已完成 */ public void verifyFlowRecordNotFinish() { if (flowRecord.isFinish()) { @@ -112,7 +133,7 @@ public void verifyFlowRecordNotFinish() { } /** - * 校验流程节点是否可编辑 + * 校验流程节点是否可编辑 */ public void verifyFlowNodeEditableState(boolean editable) { // 流程节点不可编辑时,不能保存 @@ -123,41 +144,35 @@ public void verifyFlowNodeEditableState(boolean editable) { /** - * 校验转办人员不能是当前操作者 + * 校验转办人员不能是当前操作者 */ public void verifyTargetOperatorIsNotCurrentOperator(IFlowOperator targetOperator) { - if(currentOperator.getUserId() == targetOperator.getUserId()){ + if (currentOperator.getUserId() == targetOperator.getUserId()) { throw new IllegalArgumentException("current operator is target operator"); } } /** - * 获取流程记录对象 - */ - public void loadFlowRecord() { - FlowRecord flowRecord = flowRecordRepository.getFlowRecordById(recordId); - if (flowRecord == null) { - throw new IllegalArgumentException("flow record not found"); - } - this.flowRecord = flowRecord; - } - - /** - * 获取流程设计对象 + * 获取流程设计对象 */ public void loadFlowWork() { - FlowWork flowWork = flowProcessRepository.getFlowWorkByProcessId(flowRecord.getProcessId()); - if (flowWork == null) { - throw new IllegalArgumentException("flow work not found"); + if (this.flowWork == null) { + FlowWork flowWork = flowProcessRepository.getFlowWorkByProcessId(flowRecord.getProcessId()); + if (flowWork == null) { + flowWork = flowWorkRepository.getFlowWorkByCode(flowRecord.getWorkCode()); + } + if (flowWork == null) { + throw new IllegalArgumentException("flow work not found"); + } + flowWork.enableValidate(); + this.flowWork = flowWork; } - flowWork.enableValidate(); - this.flowWork = flowWork; } /** - * 获取流程节点对象 + * 获取流程节点对象 */ public void loadFlowNode() { FlowNode flowNode = flowWork.getNodeByCode(flowRecord.getNodeCode()); @@ -168,11 +183,11 @@ public void loadFlowNode() { } /** - * 标记流程为已读状态 + * 标记流程为已读状态 */ public void setFlowRecordRead() { if (currentOperator != null) { - if(flowRecord.isOperator(currentOperator)) { + if (flowRecord.isOperator(currentOperator)) { if (!flowRecord.isRead()) { flowRecord.read(); flowRecordRepository.update(flowRecord); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index 2de3d976..a9aa8d13 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -20,16 +20,15 @@ public class FlowService { private final FlowDetailService flowDetailService; - private final FlowStartService flowStartService; - private final FlowSubmitService flowSubmitService; private final FlowCustomEventService flowCustomEventService; private final FlowRecallService flowRecallService; - private final FlowTrySubmitService flowTrySubmitService; private final FlowSaveService flowSaveService; private final FlowTransferService flowTransferService; private final FlowPostponedService flowPostponedService; private final FlowUrgeService flowUrgeService; + private final FlowServiceRepositoryHolder flowServiceRepositoryHolder; + public FlowService(FlowWorkRepository flowWorkRepository, FlowRecordRepository flowRecordRepository, @@ -37,16 +36,14 @@ public FlowService(FlowWorkRepository flowWorkRepository, FlowOperatorRepository flowOperatorRepository, FlowProcessRepository flowProcessRepository, FlowBackupRepository flowBackupRepository) { + this.flowServiceRepositoryHolder = new FlowServiceRepositoryHolder(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository, flowBackupRepository); this.flowDetailService = new FlowDetailService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository); - this.flowStartService = new FlowStartService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository, flowBackupRepository); - this.flowSubmitService = new FlowSubmitService(flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository); - this.flowCustomEventService = new FlowCustomEventService(flowRecordRepository, flowProcessRepository); - this.flowRecallService = new FlowRecallService(flowRecordRepository, flowProcessRepository); - this.flowTrySubmitService = new FlowTrySubmitService(flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository, flowWorkRepository, flowBackupRepository); - this.flowSaveService = new FlowSaveService(flowRecordRepository, flowBindDataRepository, flowProcessRepository); - this.flowTransferService = new FlowTransferService(flowRecordRepository, flowBindDataRepository, flowProcessRepository); - this.flowPostponedService = new FlowPostponedService(flowRecordRepository, flowProcessRepository); - this.flowUrgeService = new FlowUrgeService(flowRecordRepository, flowProcessRepository); + this.flowCustomEventService = new FlowCustomEventService(flowWorkRepository,flowRecordRepository, flowProcessRepository); + this.flowRecallService = new FlowRecallService(flowWorkRepository,flowRecordRepository, flowProcessRepository); + this.flowSaveService = new FlowSaveService(flowWorkRepository,flowRecordRepository, flowBindDataRepository, flowProcessRepository); + this.flowTransferService = new FlowTransferService(flowWorkRepository,flowRecordRepository, flowBindDataRepository, flowProcessRepository); + this.flowPostponedService = new FlowPostponedService(flowWorkRepository,flowRecordRepository, flowProcessRepository); + this.flowUrgeService = new FlowUrgeService(flowWorkRepository,flowRecordRepository, flowProcessRepository); } /** @@ -170,7 +167,8 @@ public void save(long recordId, IFlowOperator currentOperator, IBindData bindDat * @param advice 审批意见 */ public FlowResult startFlow(String workCode, IFlowOperator operator, IBindData bindData, String advice) { - return flowStartService.startFlow(workCode, operator, bindData, advice); + FlowStartService flowStartService = new FlowStartService(workCode, operator, bindData, advice, flowServiceRepositoryHolder); + return flowStartService.startFlow(); } @@ -183,7 +181,8 @@ public FlowResult startFlow(String workCode, IFlowOperator operator, IBindData b * @param opinion 审批意见 */ public FlowSubmitResult trySubmitFlow(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { - return flowTrySubmitService.trySubmitFlow(recordId, currentOperator, bindData, opinion); + FlowTrySubmitService flowTrySubmitService = new FlowTrySubmitService(currentOperator, bindData, opinion, flowServiceRepositoryHolder); + return flowTrySubmitService.trySubmitFlow(recordId); } @@ -196,7 +195,8 @@ public FlowSubmitResult trySubmitFlow(long recordId, IFlowOperator currentOperat * @param opinion 审批意见 */ public FlowSubmitResult trySubmitFlow(String workCode, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { - return flowTrySubmitService.trySubmitFlow(workCode, currentOperator, bindData, opinion); + FlowTrySubmitService flowTrySubmitService = new FlowTrySubmitService(currentOperator, bindData, opinion, flowServiceRepositoryHolder); + return flowTrySubmitService.trySubmitFlow(workCode); } @@ -209,7 +209,8 @@ public FlowSubmitResult trySubmitFlow(String workCode, IFlowOperator currentOper * @param opinion 审批意见 */ public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { - return flowSubmitService.submitFlow(recordId, currentOperator, bindData, opinion); + FlowSubmitService flowSubmitService = new FlowSubmitService(recordId, currentOperator, bindData, opinion, flowServiceRepositoryHolder); + return flowSubmitService.submitFlow(); } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowServiceRepositoryHolder.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowServiceRepositoryHolder.java new file mode 100644 index 00000000..20b8c8b6 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowServiceRepositoryHolder.java @@ -0,0 +1,29 @@ +package com.codingapi.springboot.flow.service; + +import com.codingapi.springboot.flow.repository.*; +import lombok.Getter; + +@Getter +public class FlowServiceRepositoryHolder { + + private final FlowWorkRepository flowWorkRepository; + private final FlowRecordRepository flowRecordRepository; + private final FlowBindDataRepository flowBindDataRepository; + private final FlowOperatorRepository flowOperatorRepository; + private final FlowProcessRepository flowProcessRepository; + private final FlowBackupRepository flowBackupRepository; + + public FlowServiceRepositoryHolder(FlowWorkRepository flowWorkRepository, + FlowRecordRepository flowRecordRepository, + FlowBindDataRepository flowBindDataRepository, + FlowOperatorRepository flowOperatorRepository, + FlowProcessRepository flowProcessRepository, + FlowBackupRepository flowBackupRepository){ + this.flowWorkRepository = flowWorkRepository; + this.flowRecordRepository = flowRecordRepository; + this.flowBindDataRepository = flowBindDataRepository; + this.flowOperatorRepository = flowOperatorRepository; + this.flowProcessRepository = flowProcessRepository; + this.flowBackupRepository = flowBackupRepository; + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowCustomEventService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowCustomEventService.java index b7ab1dfc..67fbbbd8 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowCustomEventService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowCustomEventService.java @@ -8,6 +8,7 @@ import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.FlowProcessRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; import com.codingapi.springboot.flow.result.MessageResult; import com.codingapi.springboot.flow.service.FlowRecordVerifyService; import com.codingapi.springboot.flow.user.IFlowOperator; @@ -21,6 +22,7 @@ @AllArgsConstructor public class FlowCustomEventService { + private final FlowWorkRepository flowWorkRepository; private final FlowRecordRepository flowRecordRepository; private final FlowProcessRepository flowProcessRepository; @@ -34,10 +36,8 @@ public class FlowCustomEventService { * @param opinion 审批意见 */ public MessageResult customFlowEvent(long recordId, IFlowOperator currentOperator, String buttonId, IBindData bindData, Opinion opinion) { - FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, flowProcessRepository, recordId, currentOperator); + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowWorkRepository,flowRecordRepository, flowProcessRepository, recordId, currentOperator); - // 加载流程 - flowRecordVerifyService.loadFlowRecord(); // 验证流程的提交状态 flowRecordVerifyService.verifyFlowRecordSubmitState(); // 验证当前操作者 diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java index b2ea7409..e684f422 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java @@ -36,11 +36,10 @@ public class FlowDetailService { */ public FlowDetail detail(long recordId, IFlowOperator currentOperator) { - FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowWorkRepository,flowRecordRepository, flowProcessRepository, recordId, currentOperator); - flowRecordVerifyService.loadFlowRecord(); flowRecordVerifyService.setFlowRecordRead(); flowRecordVerifyService.loadFlowWork(); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowPostponedService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowPostponedService.java index 6b11b0e5..68cbbc0f 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowPostponedService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowPostponedService.java @@ -4,6 +4,7 @@ import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.FlowProcessRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; import com.codingapi.springboot.flow.service.FlowRecordVerifyService; import com.codingapi.springboot.flow.user.IFlowOperator; import lombok.AllArgsConstructor; @@ -13,6 +14,7 @@ @AllArgsConstructor public class FlowPostponedService { + private final FlowWorkRepository flowWorkRepository; private final FlowRecordRepository flowRecordRepository; private final FlowProcessRepository flowProcessRepository; @@ -24,11 +26,10 @@ public class FlowPostponedService { * @param time 延期时间 */ public void postponed(long recordId, IFlowOperator currentOperator, long time) { - FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowWorkRepository,flowRecordRepository, flowProcessRepository, recordId, currentOperator); - flowRecordVerifyService.loadFlowRecord(); flowRecordVerifyService.verifyFlowRecordSubmitState(); flowRecordVerifyService.verifyFlowRecordCurrentOperator(); flowRecordVerifyService.loadFlowWork(); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java index e0d98d0a..124f48b8 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java @@ -5,6 +5,7 @@ import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.FlowProcessRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; import com.codingapi.springboot.flow.service.FlowRecordVerifyService; import com.codingapi.springboot.flow.user.IFlowOperator; import com.codingapi.springboot.framework.event.EventPusher; @@ -18,6 +19,7 @@ @AllArgsConstructor public class FlowRecallService { + private final FlowWorkRepository flowWorkRepository; private final FlowRecordRepository flowRecordRepository; private final FlowProcessRepository flowProcessRepository; @@ -28,11 +30,12 @@ public class FlowRecallService { * @param currentOperator 当前操作者 */ public void recall(long recordId, IFlowOperator currentOperator) { - FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService( + flowWorkRepository, + flowRecordRepository, flowProcessRepository, recordId, currentOperator); - flowRecordVerifyService.loadFlowRecord(); flowRecordVerifyService.verifyFlowRecordCurrentOperator(); flowRecordVerifyService.loadFlowWork(); flowRecordVerifyService.loadFlowNode(); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java index 174c18a3..6e57d924 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java @@ -7,6 +7,7 @@ import com.codingapi.springboot.flow.repository.FlowBindDataRepository; import com.codingapi.springboot.flow.repository.FlowProcessRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; import com.codingapi.springboot.flow.service.FlowRecordVerifyService; import com.codingapi.springboot.flow.user.IFlowOperator; import lombok.AllArgsConstructor; @@ -16,6 +17,7 @@ @AllArgsConstructor public class FlowSaveService { + private final FlowWorkRepository flowWorkRepository; private final FlowRecordRepository flowRecordRepository; private final FlowBindDataRepository flowBindDataRepository; private final FlowProcessRepository flowProcessRepository; @@ -29,10 +31,10 @@ public class FlowSaveService { * @param advice 审批意见 */ public void save(long recordId, IFlowOperator currentOperator, IBindData bindData, String advice) { - FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowWorkRepository, + flowRecordRepository, flowProcessRepository, recordId, currentOperator); - flowRecordVerifyService.loadFlowRecord(); flowRecordVerifyService.verifyFlowRecordSubmitState(); flowRecordVerifyService.verifyFlowRecordCurrentOperator(); flowRecordVerifyService.loadFlowWork(); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java index 80047a84..da90bf88 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java @@ -11,76 +11,100 @@ import com.codingapi.springboot.flow.record.FlowBackup; import com.codingapi.springboot.flow.record.FlowProcess; import com.codingapi.springboot.flow.record.FlowRecord; -import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.repository.FlowBackupRepository; +import com.codingapi.springboot.flow.repository.FlowOperatorRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; import com.codingapi.springboot.flow.service.FlowNodeService; +import com.codingapi.springboot.flow.service.FlowServiceRepositoryHolder; import com.codingapi.springboot.flow.user.IFlowOperator; import com.codingapi.springboot.framework.event.EventPusher; -import lombok.AllArgsConstructor; +import lombok.Getter; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; @Transactional -@AllArgsConstructor public class FlowStartService { - private final FlowWorkRepository flowWorkRepository; - private final FlowRecordRepository flowRecordRepository; - private final FlowBindDataRepository flowBindDataRepository; - private final FlowOperatorRepository flowOperatorRepository; - private final FlowProcessRepository flowProcessRepository; - private final FlowBackupRepository flowBackupRepository; - + private final String workCode; + private final IFlowOperator operator; + private final IBindData bindData; + private final Opinion opinion; + private final FlowServiceRepositoryHolder flowServiceRepositoryHolder; + + + @Getter + private FlowWork flowWork; + private FlowNode flowNode; + private FlowBackup flowBackup; + private FlowProcess flowProcess; + private BindDataSnapshot snapshot; + private FlowNodeService flowNodeService; + + public FlowStartService(String workCode, + IFlowOperator operator, + IBindData bindData, + String advice, + FlowServiceRepositoryHolder flowServiceRepositoryHolder) { + this.workCode = workCode; + this.operator = operator; + this.bindData = bindData; + this.opinion = Opinion.pass(advice); + this.flowServiceRepositoryHolder = flowServiceRepositoryHolder; + } - /** - * 发起流程 (不自动提交到下一节点) - * - * @param workCode 流程编码 - * @param operator 操作者 - * @param bindData 绑定数据 - * @param advice 审批意见 - */ - public FlowResult startFlow(String workCode, IFlowOperator operator, IBindData bindData, String advice) { + private void loadFlowWork() { // 检测流程是否存在 - FlowWork flowWork = flowWorkRepository.getFlowWorkByCode(workCode); + FlowWorkRepository flowWorkRepository = flowServiceRepositoryHolder.getFlowWorkRepository(); + this.flowWork = flowWorkRepository.getFlowWorkByCode(workCode); if (flowWork == null) { throw new IllegalArgumentException("flow work not found"); } flowWork.verify(); flowWork.enableValidate(); + } - // 流程数据备份 - FlowBackup flowBackup = flowBackupRepository.getFlowBackupByWorkIdAndVersion(flowWork.getId(), flowWork.getUpdateTime()); + private void loadFlowBackup() { + FlowBackupRepository flowBackupRepository = flowServiceRepositoryHolder.getFlowBackupRepository(); + this.flowBackup = flowBackupRepository.getFlowBackupByWorkIdAndVersion(flowWork.getId(), flowWork.getUpdateTime()); if (flowBackup == null) { flowBackup = flowBackupRepository.backup(flowWork); } + } - // 保存流程 - FlowProcess flowProcess = new FlowProcess(flowBackup.getId(), operator); - flowProcessRepository.save(flowProcess); - - // 保存绑定数据 - BindDataSnapshot snapshot = new BindDataSnapshot(bindData); - flowBindDataRepository.save(snapshot); + private void saveFlowProcess() { + this.flowProcess = new FlowProcess(flowBackup.getId(), operator); + flowServiceRepositoryHolder.getFlowProcessRepository().save(flowProcess); + } - // 创建流程id - String processId = flowProcess.getProcessId(); + private void saveBindDataSnapshot() { + snapshot = new BindDataSnapshot(bindData); + flowServiceRepositoryHolder.getFlowBindDataRepository().save(snapshot); + } - // 构建审批意见 - Opinion opinion = Opinion.pass(advice); + private void buildFlowNodeService() { // 获取开始节点 FlowNode start = flowWork.getStartNode(); if (start == null) { throw new IllegalArgumentException("start node not found"); } + + this.flowNode = start; // 设置开始流程的上一个流程id long preId = 0; + // 创建流程id + String processId = flowProcess.getProcessId(); + List historyRecords = new ArrayList<>(); - FlowNodeService flowNodeService = new FlowNodeService(flowOperatorRepository, + FlowOperatorRepository flowOperatorRepository = flowServiceRepositoryHolder.getFlowOperatorRepository(); + FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + + flowNodeService = new FlowNodeService(flowOperatorRepository, flowRecordRepository, snapshot, opinion, @@ -93,6 +117,43 @@ public FlowResult startFlow(String workCode, IFlowOperator operator, IBindData b preId); flowNodeService.setNextNode(start); + } + + + private void pushEvent(int flowApprovalEventState, FlowRecord flowRecord) { + EventPusher.push(new FlowApprovalEvent(flowApprovalEventState, + flowRecord, + flowRecord.getCurrentOperator(), + flowWork, + snapshot.toBindData()), + true); + } + + + private void saveFlowRecords(List flowRecords) { + FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + flowRecordRepository.save(flowRecords); + } + + + /** + * 发起流程 (不自动提交到下一节点) + */ + public FlowResult startFlow() { + // 检测流程是否存在 + this.loadFlowWork(); + + // 流程数据备份 + this.loadFlowBackup(); + + // 保存流程 + this.saveFlowProcess(); + + // 保存绑定数据 + this.saveBindDataSnapshot(); + + // 构建流程节点服务 + this.buildFlowNodeService(); // 创建待办记录 List records = flowNodeService.createRecord(); @@ -111,32 +172,64 @@ public FlowResult startFlow(String workCode, IFlowOperator operator, IBindData b record.finish(); } - flowRecordRepository.save(records); + this.saveFlowRecords(records); // 推送事件 for (FlowRecord record : records) { - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_CREATE, record, operator, flowWork, snapshot.toBindData()), true); - - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_FINISH, - record, - operator, - flowWork, - snapshot.toBindData()), - true); + this.pushEvent(FlowApprovalEvent.STATE_CREATE, record); + this.pushEvent(FlowApprovalEvent.STATE_FINISH, record); } return new FlowResult(flowWork, records); } // 保存流程记录 - flowRecordRepository.save(records); + this.saveFlowRecords(records); // 推送事件消息 for (FlowRecord record : records) { - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_CREATE, record, operator, flowWork, snapshot.toBindData()), true); - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, record, operator, flowWork, snapshot.toBindData()), true); + this.pushEvent(FlowApprovalEvent.STATE_CREATE, record); + this.pushEvent(FlowApprovalEvent.STATE_TODO, record); } // 当前的审批记录 return new FlowResult(flowWork, records); } + + public FlowRecord tryStartFlow() { + // 检测流程是否存在 + this.loadFlowWork(); + // 流程数据备份 + this.loadFlowBackup(); + + // 保存绑定数据 + snapshot = new BindDataSnapshot(bindData); + // 保存流程 + flowProcess = new FlowProcess(flowBackup.getId(), operator); + + // 构建流程节点服务 + this.buildFlowNodeService(); + + FlowRecord startRecord = null; + + // 创建待办记录 + List records = flowNodeService.createRecord(); + if (records.isEmpty()) { + throw new IllegalArgumentException("flow record not found"); + } else { + for (FlowRecord record : records) { + record.updateOpinion(opinion); + startRecord = record; + } + } + + // 检测流程是否结束 + if (flowNodeService.nextNodeIsOver()) { + for (FlowRecord record : records) { + record.submitRecord(operator, snapshot, opinion, FlowSourceDirection.PASS); + record.finish(); + startRecord = record; + } + } + return startRecord; + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index 3f1b1136..610a22cd 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -8,17 +8,16 @@ import com.codingapi.springboot.flow.em.FlowSourceDirection; import com.codingapi.springboot.flow.event.FlowApprovalEvent; import com.codingapi.springboot.flow.pojo.FlowResult; +import com.codingapi.springboot.flow.pojo.FlowSubmitResult; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.FlowBindDataRepository; -import com.codingapi.springboot.flow.repository.FlowOperatorRepository; -import com.codingapi.springboot.flow.repository.FlowProcessRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; import com.codingapi.springboot.flow.service.FlowDirectionService; import com.codingapi.springboot.flow.service.FlowNodeService; import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.service.FlowServiceRepositoryHolder; import com.codingapi.springboot.flow.user.IFlowOperator; import com.codingapi.springboot.framework.event.EventPusher; -import lombok.AllArgsConstructor; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; @@ -26,32 +25,74 @@ import java.util.stream.Collectors; @Transactional -@AllArgsConstructor public class FlowSubmitService { - private final FlowRecordRepository flowRecordRepository; - private final FlowBindDataRepository flowBindDataRepository; - private final FlowOperatorRepository flowOperatorRepository; - private final FlowProcessRepository flowProcessRepository; - /** - * 提交流程 - * - * @param recordId 流程记录id - * @param currentOperator 当前操作者 - * @param bindData 绑定数据 - * @param opinion 审批意见 - */ - public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + private final IFlowOperator currentOperator; + private final IBindData bindData; + private final Opinion opinion; + private final FlowServiceRepositoryHolder flowServiceRepositoryHolder; + private final FlowRecordVerifyService flowRecordVerifyService; + - FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, flowProcessRepository, recordId, currentOperator); + private FlowRecord flowRecord; + private FlowWork flowWork; + private FlowNode flowNode; + private FlowNode nextNode; + + + private BindDataSnapshot snapshot; + private FlowNodeService flowNodeService; + private FlowDirectionService flowDirectionService; + private FlowSourceDirection flowSourceDirection; + + + public FlowSubmitService(long recordId, + IFlowOperator currentOperator, + IBindData bindData, + Opinion opinion, + FlowServiceRepositoryHolder flowServiceRepositoryHolder) { + this.flowServiceRepositoryHolder = flowServiceRepositoryHolder; + this.currentOperator = currentOperator; + this.bindData = bindData; + this.opinion = opinion; + this.flowRecordVerifyService = new FlowRecordVerifyService( + flowServiceRepositoryHolder.getFlowWorkRepository(), + flowServiceRepositoryHolder.getFlowRecordRepository(), + flowServiceRepositoryHolder.getFlowProcessRepository(), + recordId, + currentOperator); + } - // 加载流程 - flowRecordVerifyService.loadFlowRecord(); + + public FlowSubmitService(FlowRecord flowRecord, + FlowWork flowWork, + IFlowOperator currentOperator, + IBindData bindData, + Opinion opinion, + FlowServiceRepositoryHolder flowServiceRepositoryHolder) { + this.flowWork = flowWork; + this.flowServiceRepositoryHolder = flowServiceRepositoryHolder; + this.currentOperator = currentOperator; + this.bindData = bindData; + this.opinion = opinion; + this.flowRecordVerifyService = new FlowRecordVerifyService( + flowServiceRepositoryHolder.getFlowWorkRepository(), + flowServiceRepositoryHolder.getFlowRecordRepository(), + flowServiceRepositoryHolder.getFlowProcessRepository(), + flowRecord, + flowWork, + currentOperator); + } + + + // 加载流程 + private void loadFlow(boolean testSubmit) { // 验证流程的提交状态 flowRecordVerifyService.verifyFlowRecordSubmitState(); // 验证当前操作者 flowRecordVerifyService.verifyFlowRecordCurrentOperator(); + // 加载流程设计 flowRecordVerifyService.loadFlowWork(); // 加载流程节点 @@ -59,72 +100,84 @@ public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBind // 验证没有子流程 flowRecordVerifyService.verifyChildrenRecordsIsEmpty(); - // 获取流程记录对象 - FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); - FlowNode flowNode = flowRecordVerifyService.getFlowNode(); - FlowWork flowWork = flowRecordVerifyService.getFlowWork(); - + if (testSubmit) { + this.flowRecord = flowRecordVerifyService.getFlowRecord().copy(); + } else { + this.flowRecord = flowRecordVerifyService.getFlowRecord(); + } + this.flowNode = flowRecordVerifyService.getFlowNode(); + this.flowWork = flowRecordVerifyService.getFlowWork(); + } - // 保存流程表单快照数据 - BindDataSnapshot snapshot = null; + // 保存流程表单快照数据 + private void saveSnapshot(boolean testSubmit) { + FlowBindDataRepository flowBindDataRepository = flowServiceRepositoryHolder.getFlowBindDataRepository(); if (flowNode.isEditable()) { snapshot = new BindDataSnapshot(bindData); - flowBindDataRepository.save(snapshot); + if (!testSubmit) { + flowBindDataRepository.save(snapshot); + } } else { snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); } + } + // 加载流程审批方向 + private void loadFlowDirection() { // 审批方向判断服务 - FlowDirectionService flowDirectionService = new FlowDirectionService(flowRecordVerifyService.getFlowNode(), flowRecordVerifyService.getFlowWork(), opinion); + flowDirectionService = new FlowDirectionService(flowRecordVerifyService.getFlowNode(), flowRecordVerifyService.getFlowWork(), opinion); // 加载流程审批方向 flowDirectionService.loadFlowSourceDirection(); // 验证审批方向 flowDirectionService.verifyFlowSourceDirection(); - // 根据当前方向提交流程 - FlowSourceDirection flowSourceDirection = flowDirectionService.getFlowSourceDirection(); - flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); - flowRecordRepository.update(flowRecord); + flowSourceDirection = flowDirectionService.getFlowSourceDirection(); + } + + // 与当前流程同级的流程记录 + private List loadHistoryRecords(boolean testSubmit) { + FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); // 与当前流程同级的流程记录 List historyRecords; if (flowRecord.isStartRecord()) { historyRecords = new ArrayList<>(); } else { - historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()); - } - flowDirectionService.bindHistoryRecords(historyRecords); + if (testSubmit) { + // copy 流程数据防止影响原有数据 + historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()).stream().map(FlowRecord::copy).collect(Collectors.toList()); + // 更新当前流程记录, 由于try测试过程中没有对数据落库,所以这里需要手动更新 + for (FlowRecord record : historyRecords) { + if (record.getId() == flowRecord.getId()) { + record.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); + } + } - // 判断流程是否结束(会签时需要所有人都通过) - if (flowNode.isSign()) { - boolean isDone = flowDirectionService.hasCurrentFlowNodeIsDone(); - if (!isDone) { - List todoRecords = historyRecords.stream().filter(FlowRecord::isTodo).collect(Collectors.toList()); - return new FlowResult(flowWork, todoRecords); + } else { + historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()); } } + return historyRecords; + } - // 非会签下,当有人提交以后,将所有未提交的流程都自动提交,然后再执行下一节点 - if (flowNode.isUnSign()) { - for (FlowRecord record : historyRecords) { - if (record.isTodo() && record.getId() != flowRecord.getId()) { - record.autoPass(currentOperator, snapshot); - flowRecordRepository.update(flowRecord); - } - } - } - // 根据所有提交意见,重新加载审批方向 - flowSourceDirection = flowDirectionService.reloadFlowSourceDirection(); + // 保存流程记录 + private void saveFlowRecord(FlowRecord flowRecord) { + FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + flowRecordRepository.update(flowRecord); + } + + // 生成下一节点的流程记录 + private void loadNextNode(List historyRecords) { // 获取流程的发起者 IFlowOperator createOperator = flowRecord.getCreateOperator(); // 构建流程创建器 - FlowNodeService flowNodeService = new FlowNodeService( - flowOperatorRepository, - flowRecordRepository, + flowNodeService = new FlowNodeService( + flowServiceRepositoryHolder.getFlowOperatorRepository(), + flowServiceRepositoryHolder.getFlowRecordRepository(), snapshot, opinion, createOperator, @@ -146,51 +199,184 @@ public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBind // 审批拒绝,并且自定了返回节点 flowNodeService.loadCustomBackNode(flowNode, flowRecord.getPreId()); } + this.nextNode = flowNodeService.getNextNode(); + } + + + // 更新流程记录 + private void updateFinishFlowRecord() { + flowServiceRepositoryHolder.getFlowRecordRepository().finishFlowRecordByProcessId(flowRecord.getProcessId()); + } + + // 保存流程记录 + private void saveFlowRecords(List flowRecords) { + flowServiceRepositoryHolder.getFlowRecordRepository().save(flowRecords); + } + + // 推送审批事件消息 + private void pushEvent(FlowRecord flowRecord, int eventState) { + EventPusher.push(new FlowApprovalEvent(eventState, + flowRecord, + flowRecord.getCurrentOperator(), + flowWork, + snapshot.toBindData() + ), true); + } + + + /** + * 提交流程 根据流程的是否跳过相同审批人来判断是否需要继续提交 + * + * @return 流程结果 + */ + public FlowResult submitFlow() { + FlowResult flowResult = this.submitCurrentFlow(); + if (this.isSkipIfSameApprover()) { + List flowRecords = flowResult.matchRecordByOperator(currentOperator); + FlowResult result = flowResult; + if (!flowRecords.isEmpty()) { + for (FlowRecord flowRecord : flowRecords) { + FlowSubmitService flowSubmitService = new FlowSubmitService(flowRecord.getId(), currentOperator, bindData, opinion, flowServiceRepositoryHolder); + result = flowSubmitService.submitCurrentFlow(); + } + } + return result; + } else { + return flowResult; + } + } + + /** + * 提交当前流程 + * + * @return 流程结果 + */ + private FlowResult submitCurrentFlow() { + // 加载流程信息 + this.loadFlow(false); + + // 保存流程表单快照数据 + this.saveSnapshot(false); + + // 审批方向判断服务 + this.loadFlowDirection(); + + // 提交流程记录 + flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); + this.saveFlowRecord(flowRecord); + + // 与当前流程同级的流程记录 + List historyRecords = this.loadHistoryRecords(false); + flowDirectionService.bindHistoryRecords(historyRecords); + + // 判断流程是否结束(会签时需要所有人都通过) + if (flowNode.isSign()) { + boolean isDone = flowDirectionService.hasCurrentFlowNodeIsDone(); + if (!isDone) { + List todoRecords = historyRecords.stream().filter(FlowRecord::isTodo).collect(Collectors.toList()); + return new FlowResult(flowWork, todoRecords); + } + } - List records = flowNodeService.createRecord(); + // 非会签下,当有人提交以后,将所有未提交的流程都自动提交,然后再执行下一节点 + if (flowNode.isUnSign()) { + for (FlowRecord record : historyRecords) { + if (record.isTodo() && record.getId() != flowRecord.getId()) { + record.autoPass(currentOperator, snapshot); + FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + flowRecordRepository.update(flowRecord); + } + } + } + + // 根据所有提交意见,重新加载审批方向 + flowSourceDirection = flowDirectionService.reloadFlowSourceDirection(); + + this.loadNextNode(historyRecords); + + // 生成下一节点的流程记录 + List nextRecords = flowNodeService.createRecord(); // 判断流程是否完成 if (flowNodeService.nextNodeIsOver()) { flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); flowRecord.finish(); - flowRecordRepository.update(flowRecord); - flowRecordRepository.finishFlowRecordByProcessId(flowRecord.getProcessId()); - - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_FINISH, - flowRecord, - currentOperator, - flowWork, - snapshot.toBindData()), - true); - if(!records.isEmpty()) { - return new FlowResult(flowWork, records.get(0)); + this.saveFlowRecord(flowRecord); + this.updateFinishFlowRecord(); + + this.pushEvent(flowRecord, FlowApprovalEvent.STATE_CREATE); + + if (!nextRecords.isEmpty()) { + return new FlowResult(flowWork, nextRecords.get(0)); } return new FlowResult(flowWork, flowRecord); } // 保存流程记录 - flowRecordRepository.save(records); + this.saveFlowRecords(nextRecords); // 推送审批事件消息 int eventState = flowSourceDirection == FlowSourceDirection.PASS ? FlowApprovalEvent.STATE_PASS : FlowApprovalEvent.STATE_REJECT; - EventPusher.push(new FlowApprovalEvent(eventState, - flowRecord, - currentOperator, - flowWork, - snapshot.toBindData()), - true); + this.pushEvent(flowRecord, eventState); // 推送待办事件消息 - for (FlowRecord record : records) { - IFlowOperator pushOperator = record.getCurrentOperator(); - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, - record, - pushOperator, - flowWork, - snapshot.toBindData()), - true); + for (FlowRecord record : nextRecords) { + this.pushEvent(record, FlowApprovalEvent.STATE_TODO); } - return new FlowResult(flowWork, records); + return new FlowResult(flowWork, nextRecords); + } + + /** + * 提交流程 + **/ + public FlowSubmitResult trySubmitFlow() { + // 加载流程信息 + this.loadFlow(true); + + // 保存流程表单快照数据 + this.saveSnapshot(true); + + // 审批方向判断服务 + this.loadFlowDirection(); + + // 提交流程记录 + flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); + + // 与当前流程同级的流程记录 + List historyRecords = this.loadHistoryRecords(true); + flowDirectionService.bindHistoryRecords(historyRecords); + + // 判断流程是否结束(会签时需要所有人都通过) + if (flowNode.isSign()) { + boolean isDone = flowDirectionService.hasCurrentFlowNodeIsDone(); + if (!isDone) { + List todoRecords = historyRecords.stream().filter(FlowRecord::isTodo).collect(Collectors.toList()); + return new FlowSubmitResult(flowWork, flowNode, todoRecords.stream().map(FlowRecord::getCurrentOperator).collect(Collectors.toList())); + } + } + + // 非会签下,当有人提交以后,将所有未提交的流程都自动提交,然后再执行下一节点 + if (flowNode.isUnSign()) { + for (FlowRecord record : historyRecords) { + if (record.isTodo() && record.getId() != flowRecord.getId()) { + record.autoPass(currentOperator, snapshot); + } + } + } + + // 根据所有提交意见,重新加载审批方向 + flowSourceDirection = flowDirectionService.reloadFlowSourceDirection(); + + this.loadNextNode(historyRecords); + + List operators = flowNodeService.loadNextNodeOperators(); + return new FlowSubmitResult(flowWork, nextNode, operators); + } + + + // 是否跳过相同审批人 + public boolean isSkipIfSameApprover() { + return flowWork.isSkipIfSameApprover() && !nextNode.isOverNode(); } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTransferService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTransferService.java index 429d79f7..fc6e8007 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTransferService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTransferService.java @@ -11,6 +11,7 @@ import com.codingapi.springboot.flow.repository.FlowBindDataRepository; import com.codingapi.springboot.flow.repository.FlowProcessRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; import com.codingapi.springboot.flow.service.FlowRecordVerifyService; import com.codingapi.springboot.flow.user.IFlowOperator; import com.codingapi.springboot.framework.event.EventPusher; @@ -25,6 +26,7 @@ @AllArgsConstructor public class FlowTransferService { + private final FlowWorkRepository flowWorkRepository; private final FlowRecordRepository flowRecordRepository; private final FlowBindDataRepository flowBindDataRepository; private final FlowProcessRepository flowProcessRepository; @@ -41,11 +43,10 @@ public class FlowTransferService { */ public void transfer(long recordId, IFlowOperator currentOperator, IFlowOperator targetOperator, IBindData bindData, String advice) { - FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowWorkRepository, flowRecordRepository, flowProcessRepository, recordId, currentOperator); - flowRecordVerifyService.loadFlowRecord(); flowRecordVerifyService.verifyFlowRecordSubmitState(); flowRecordVerifyService.verifyFlowRecordCurrentOperator(); flowRecordVerifyService.verifyTargetOperatorIsNotCurrentOperator(targetOperator); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java index d80ed9f4..a136f492 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java @@ -1,256 +1,44 @@ package com.codingapi.springboot.flow.service.impl; -import com.codingapi.springboot.flow.bind.BindDataSnapshot; import com.codingapi.springboot.flow.bind.IBindData; -import com.codingapi.springboot.flow.domain.FlowNode; -import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.domain.Opinion; -import com.codingapi.springboot.flow.em.FlowSourceDirection; import com.codingapi.springboot.flow.pojo.FlowSubmitResult; -import com.codingapi.springboot.flow.record.FlowBackup; -import com.codingapi.springboot.flow.record.FlowProcess; import com.codingapi.springboot.flow.record.FlowRecord; -import com.codingapi.springboot.flow.repository.*; -import com.codingapi.springboot.flow.service.FlowDirectionService; -import com.codingapi.springboot.flow.service.FlowNodeService; -import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.service.FlowServiceRepositoryHolder; import com.codingapi.springboot.flow.user.IFlowOperator; -import lombok.AllArgsConstructor; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - @Transactional -@AllArgsConstructor public class FlowTrySubmitService { - private final FlowRecordRepository flowRecordRepository; - private final FlowBindDataRepository flowBindDataRepository; - private final FlowOperatorRepository flowOperatorRepository; - private final FlowProcessRepository flowProcessRepository; - private final FlowWorkRepository flowWorkRepository; - private final FlowBackupRepository flowBackupRepository; - - - /** - * 尝试提交流程 (流程过程中) - * - * @param recordId 流程记录id - * @param currentOperator 当前操作者 - * @param bindData 绑定数据 - * @param opinion 审批意见 - */ - public FlowSubmitResult trySubmitFlow(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { - - FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, flowProcessRepository, recordId, currentOperator); - - // 加载流程 - flowRecordVerifyService.loadFlowRecord(); - // 验证流程的提交状态 - flowRecordVerifyService.verifyFlowRecordSubmitState(); - // 验证当前操作者 - flowRecordVerifyService.verifyFlowRecordCurrentOperator(); - // 加载流程设计 - flowRecordVerifyService.loadFlowWork(); - // 加载流程节点 - flowRecordVerifyService.loadFlowNode(); - // 验证没有子流程 - flowRecordVerifyService.verifyChildrenRecordsIsEmpty(); - - // 获取流程记录对象 copy 流程数据防止影响原有数据 - FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord().copy(); - FlowNode flowNode = flowRecordVerifyService.getFlowNode(); - FlowWork flowWork = flowRecordVerifyService.getFlowWork(); - - return trySubmitFlow(flowWork, flowNode, flowRecord, currentOperator, bindData, opinion); + private final IFlowOperator currentOperator; + private final IBindData bindData; + private final Opinion opinion; + private final FlowServiceRepositoryHolder flowServiceRepositoryHolder; + + public FlowTrySubmitService(IFlowOperator currentOperator, + IBindData bindData, + Opinion opinion, + FlowServiceRepositoryHolder flowServiceRepositoryHolder) { + this.currentOperator = currentOperator; + this.bindData = bindData; + this.opinion = opinion; + this.flowServiceRepositoryHolder = flowServiceRepositoryHolder; } - /** - * 预提交流程数据查询 - * - * @param flowWork 流程设计 - * @param flowNode 流程节点 - * @param flowRecord 流程记录 - * @param currentOperator 当前操作者 - * @param bindData 绑定数据 - * @param opinion 审批意见 - * @return FlowSubmitResult - */ - private FlowSubmitResult trySubmitFlow(FlowWork flowWork, FlowNode flowNode, FlowRecord flowRecord, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { - - // 保存流程表单快照数据 - BindDataSnapshot snapshot = null; - if (flowNode.isEditable()) { - snapshot = new BindDataSnapshot(bindData); - } else { - snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); - } - - // 审批方向判断服务 - FlowDirectionService flowDirectionService = new FlowDirectionService(flowNode, flowWork, opinion); - - // 加载流程审批方向 - flowDirectionService.loadFlowSourceDirection(); - // 验证审批方向 - flowDirectionService.verifyFlowSourceDirection(); - - // 根据当前方向提交流程 - FlowSourceDirection flowSourceDirection = flowDirectionService.getFlowSourceDirection(); - flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); - - // 与当前流程同级的流程记录 - List historyRecords; - if (flowRecord.isStartRecord()) { - historyRecords = new ArrayList<>(); - } else { - // copy 流程数据防止影响原有数据 - historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()).stream().map(FlowRecord::copy).collect(Collectors.toList()); - // 更新当前流程记录, 由于try测试过程中没有对数据落库,所以这里需要手动更新 - for(FlowRecord record : historyRecords){ - if(record.getId() == flowRecord.getId()){ - record.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); - } - } - } - flowDirectionService.bindHistoryRecords(historyRecords); - - // 判断流程是否结束(会签时需要所有人都通过) - if (flowNode.isSign()) { - boolean isDone = flowDirectionService.hasCurrentFlowNodeIsDone(); - if (!isDone) { - List todoRecords = historyRecords.stream().filter(FlowRecord::isTodo).collect(Collectors.toList()); - return new FlowSubmitResult(flowWork, flowNode, todoRecords.stream().map(FlowRecord::getCurrentOperator).collect(Collectors.toList())); - } - } - - // 非会签下,当有人提交以后,将所有未提交的流程都自动提交,然后再执行下一节点 - if (flowNode.isUnSign()) { - for (FlowRecord record : historyRecords) { - if (record.isTodo() && record.getId() != flowRecord.getId()) { - record.autoPass(currentOperator, snapshot); - } - } - } - - // 根据所有提交意见,重新加载审批方向 - flowDirectionService.reloadFlowSourceDirection(); - - // 获取流程的发起者 - IFlowOperator createOperator = flowRecord.getCreateOperator(); - - // 构建流程创建器 - FlowNodeService flowNodeService = new FlowNodeService( - flowOperatorRepository, - flowRecordRepository, - snapshot, - opinion, - createOperator, - currentOperator, - historyRecords, - flowWork, - flowRecord, - flowRecord.getProcessId(), - flowRecord.getId() - ); - - // 审批通过并进入下一节点 - if (flowDirectionService.isPassRecord()) { - flowNodeService.loadNextPassNode(flowNode); - // 审批拒绝返回上一节点 - } else if (flowDirectionService.isDefaultBackRecord()) { - flowNodeService.loadDefaultBackNode(flowRecord.getPreId()); - } else { - // 审批拒绝,并且自定了返回节点 - flowNodeService.loadCustomBackNode(flowNode, flowRecord.getPreId()); - } - - FlowNode nextNode = flowNodeService.getNextNode(); - - List operators = flowNodeService.loadNextNodeOperators(); - return new FlowSubmitResult(flowWork, nextNode, operators); + public FlowSubmitResult trySubmitFlow(long recordId) { + FlowSubmitService flowSubmitService = new FlowSubmitService(recordId, currentOperator, bindData, opinion, flowServiceRepositoryHolder); + return flowSubmitService.trySubmitFlow(); } - /** - * 尝试提交流程 (发起流程) - * - * @param workCode 流程编码 - * @param currentOperator 当前操作者 - * @param bindData 绑定数据 - * @param opinion 审批意见 - */ - public FlowSubmitResult trySubmitFlow(String workCode, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { - // 检测流程是否存在 - FlowWork flowWork = flowWorkRepository.getFlowWorkByCode(workCode); - if (flowWork == null) { - throw new IllegalArgumentException("flow work not found"); - } - flowWork.verify(); - flowWork.enableValidate(); - - // 流程数据备份 - FlowBackup flowBackup = flowBackupRepository.getFlowBackupByWorkIdAndVersion(flowWork.getId(), flowWork.getUpdateTime()); - if (flowBackup == null) { - flowBackup = flowBackupRepository.backup(flowWork); - } - - // 保存流程 - FlowProcess flowProcess = new FlowProcess(flowBackup.getId(), currentOperator); - - // 保存绑定数据 - BindDataSnapshot snapshot = new BindDataSnapshot(bindData); - - // 创建流程id - String processId = flowProcess.getProcessId(); + public FlowSubmitResult trySubmitFlow(String workCode) { + FlowStartService flowStartService = new FlowStartService(workCode, currentOperator, bindData, opinion.getAdvice(), flowServiceRepositoryHolder); + FlowRecord flowRecord = flowStartService.tryStartFlow(); - // 获取开始节点 - FlowNode start = flowWork.getStartNode(); - if (start == null) { - throw new IllegalArgumentException("start node not found"); - } - // 设置开始流程的上一个流程id - long preId = 0; - - List historyRecords = new ArrayList<>(); - - FlowNodeService flowNodeService = new FlowNodeService(flowOperatorRepository, - flowRecordRepository, - snapshot, - opinion, - currentOperator, - currentOperator, - historyRecords, - flowWork, - null, - processId, - preId); - - flowNodeService.setNextNode(start); - - FlowRecord startRecord = null; - - // 创建待办记录 - List records = flowNodeService.createRecord(); - if (records.isEmpty()) { - throw new IllegalArgumentException("flow record not found"); - } else { - for (FlowRecord record : records) { - record.updateOpinion(opinion); - startRecord = record; - } - } - - // 检测流程是否结束 - if (flowNodeService.nextNodeIsOver()) { - for (FlowRecord record : records) { - record.submitRecord(currentOperator, snapshot, opinion, FlowSourceDirection.PASS); - record.finish(); - startRecord = record; - } - } - return this.trySubmitFlow(flowWork, start, startRecord, currentOperator, bindData, opinion); + FlowSubmitService flowSubmitService = new FlowSubmitService(flowRecord, flowStartService.getFlowWork(), currentOperator, bindData, opinion, flowServiceRepositoryHolder); + return flowSubmitService.trySubmitFlow(); } + } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowUrgeService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowUrgeService.java index 2ebfbfb8..ba2acda2 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowUrgeService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowUrgeService.java @@ -5,6 +5,7 @@ import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.FlowProcessRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; import com.codingapi.springboot.flow.service.FlowRecordVerifyService; import com.codingapi.springboot.flow.user.IFlowOperator; import com.codingapi.springboot.framework.event.EventPusher; @@ -18,6 +19,7 @@ public class FlowUrgeService { + private final FlowWorkRepository flowWorkRepository; private final FlowRecordRepository flowRecordRepository; private final FlowProcessRepository flowProcessRepository; @@ -28,10 +30,11 @@ public class FlowUrgeService { * @param currentOperator 当前操作者 */ public void urge(long recordId, IFlowOperator currentOperator) { - FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService(flowRecordRepository, + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService( + flowWorkRepository, + flowRecordRepository, flowProcessRepository, recordId, currentOperator); - flowRecordVerifyService.loadFlowRecord(); flowRecordVerifyService.loadFlowWork(); flowRecordVerifyService.verifyFlowRecordIsDone(); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java index 113facaa..9a8b88ec 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java @@ -132,6 +132,83 @@ void entrustTest() { + + /** + * 自己审批时直接通过 + */ + @Test + void sameUserFlow() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .skipIfSameApprover(true) + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交委托dept部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + + } + + /** * 同意再拒绝 */ diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 8306aaa3..bf37ce61 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.16 + 2.9.17 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 4e33f654..39b52e01 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.16 + 2.9.17 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 3c735191..e421e5bf 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.16 +CodingApi SpringBoot-Starter 2.9.17 springboot version (${spring-boot.version}) ------------------------------------------------------ From 5a75142d764ba9fd2650e85b44cb5cec2de21785 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 2 Jan 2025 22:39:12 +0800 Subject: [PATCH 076/129] update 2.9.18 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../codingapi/springboot/flow/matcher/OperatorMatcher.java | 4 ++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 7 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index bfc27db6..bc7d5bcf 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.17 + 2.9.18 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 39c26c89..9c5f9578 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.17 + 2.9.18 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 07a6998e..d68ea8c9 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.17 + 2.9.18 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 40335d3a..cd307f12 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.17 + 2.9.18 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java index 9580251f..e383d076 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java @@ -5,6 +5,7 @@ import lombok.Getter; import org.springframework.util.StringUtils; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -113,6 +114,9 @@ public static OperatorMatcher creatorOperatorMatcher() { */ public List matcher(FlowSession flowSession) { List values = (List) runtime.invokeMethod("run", flowSession); + if (values == null) { + return new ArrayList<>(); + } return values.stream().map(item -> { if (item instanceof Number) { return ((Number) item).longValue(); diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index bf37ce61..225ce9c4 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.17 + 2.9.18 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 39b52e01..c982fa64 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.17 + 2.9.18 springboot-starter From 2297e2eefde4fea261d1dd87c9be9de311760a81 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 3 Jan 2025 10:17:22 +0800 Subject: [PATCH 077/129] update 2.9.19 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/content/FlowSession.java | 26 ++++++++++++++++++- .../flow/content/FlowSessionBeanProvider.java | 7 +++++ .../flow/query/FlowRecordQuery.java | 14 ++++++++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 10 files changed, 53 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index bc7d5bcf..6d980a16 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.18 + 2.9.19 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 9c5f9578..54619d80 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.18 + 2.9.19 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index d68ea8c9..86714e32 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.18 + 2.9.19 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index cd307f12..c9259613 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.18 + 2.9.19 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java index 515d42d9..3050e218 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java @@ -4,10 +4,12 @@ import com.codingapi.springboot.flow.domain.FlowNode; import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.FlowSourceDirection; import com.codingapi.springboot.flow.error.NodeResult; import com.codingapi.springboot.flow.error.OperatorResult; import com.codingapi.springboot.flow.pojo.FlowResult; import com.codingapi.springboot.flow.pojo.FlowSubmitResult; +import com.codingapi.springboot.flow.query.FlowRecordQuery; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.result.MessageResult; import com.codingapi.springboot.flow.service.FlowService; @@ -66,9 +68,13 @@ public Object getBean(String beanName) { } + public T getBean(Class clazz) { + return provider.getBean(clazz); + } + /** - * 获取审批意见 + * 获取审批意见 */ public String getAdvice() { if (opinion != null) { @@ -177,6 +183,24 @@ public MessageResult rejectFlow() { return MessageResult.create(result); } + /** + * 是否为驳回状态 + * + * @return 是否为驳回状态 + */ + public boolean isRejectState() { + long preId = flowRecord.getPreId(); + if (preId == 0) { + return false; + } + FlowRecordQuery flowRecordQuery = getBean(FlowRecordQuery.class); + FlowRecord preRecord = flowRecordQuery.getFlowRecordById(preId); + if (preRecord != null) { + return preRecord.getFlowSourceDirection() == FlowSourceDirection.REJECT; + } + return false; + } + /** * 预提交流程 diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSessionBeanProvider.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSessionBeanProvider.java index 58b9351d..06731b8c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSessionBeanProvider.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSessionBeanProvider.java @@ -27,4 +27,11 @@ public Object getBean(String beanName) { return null; } + public T getBean(Class clazz) { + if (spring != null) { + return spring.getBean(clazz); + } + return null; + } + } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java index 75a7a5cd..1c365cfc 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java @@ -10,9 +10,23 @@ public interface FlowRecordQuery { + /** + * 根据ID获取流程记录 + * @param id 流程记录ID + * @return 流程记录 + */ + FlowRecord getFlowRecordById(long id); + + + /** + * 查询所有流程记录 + * @param pageRequest 分页参数 + * @return 流程记录 + */ Page findAll(PageRequest pageRequest); + /** * 查看个人的未读与待办数据 * diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 225ce9c4..14d9e840 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.18 + 2.9.19 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index c982fa64..b5a00b5a 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.18 + 2.9.19 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index e421e5bf..4656f428 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.17 +CodingApi SpringBoot-Starter 2.9.19 springboot version (${spring-boot.version}) ------------------------------------------------------ From 31a88d3bb5e3d31542a83a612634aaa3779b5f08 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 3 Jan 2025 12:02:50 +0800 Subject: [PATCH 078/129] update 2.9.20 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- .../authorization/interceptor/DefaultSQLInterceptor.java | 5 +++++ springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/service/impl/FlowSubmitService.java | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- springboot-starter/src/main/resources/META-INF/banner.txt | 2 +- 9 files changed, 13 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 6d980a16..73deeb55 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.19 + 2.9.20 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 54619d80..cb2e5a7a 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.19 + 2.9.20 springboot-starter-data-authorization diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DefaultSQLInterceptor.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DefaultSQLInterceptor.java index 8d658633..47bb18bf 100644 --- a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DefaultSQLInterceptor.java +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DefaultSQLInterceptor.java @@ -21,6 +21,11 @@ public boolean beforeHandler(String sql) { @Override public void afterHandler(String sql, String newSql, SQLException exception) { + if(exception!=null){ + log.error("sql:{}",sql); + log.error("newSql:{}",newSql); + log.error(exception.getMessage(),exception); + } if (DataAuthorizationPropertyContext.getInstance().showSql()) { log.info("newSql:{}", newSql); } diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 86714e32..265505cd 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.19 + 2.9.20 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index c9259613..cdedcc96 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.19 + 2.9.20 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index 610a22cd..c63970e1 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -304,7 +304,7 @@ private FlowResult submitCurrentFlow() { this.saveFlowRecord(flowRecord); this.updateFinishFlowRecord(); - this.pushEvent(flowRecord, FlowApprovalEvent.STATE_CREATE); + this.pushEvent(flowRecord, FlowApprovalEvent.STATE_FINISH); if (!nextRecords.isEmpty()) { return new FlowResult(flowWork, nextRecords.get(0)); diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 14d9e840..95efd861 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.19 + 2.9.20 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index b5a00b5a..ae099bac 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.19 + 2.9.20 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 4656f428..24160f8e 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.19 +CodingApi SpringBoot-Starter 2.9.20 springboot version (${spring-boot.version}) ------------------------------------------------------ From 2c09484544f7c268b34137e834e36697cd64cba1 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 3 Jan 2025 22:08:29 +0800 Subject: [PATCH 079/129] update 2.9.21 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/content/FlowSession.java | 30 ++++++++++++++++--- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 8 files changed, 33 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index 73deeb55..66ed8121 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.20 + 2.9.21 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index cb2e5a7a..a27a5c21 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.20 + 2.9.21 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 265505cd..58d364d6 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.20 + 2.9.21 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index cdedcc96..cc0dfe6d 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.20 + 2.9.21 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java index 3050e218..7d8accd4 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java @@ -184,11 +184,13 @@ public MessageResult rejectFlow() { } /** - * 是否为驳回状态 - * - * @return 是否为驳回状态 + * 上级节点的状态是驳回状态 + * @return 上级节点的状态是驳回状态 */ - public boolean isRejectState() { + public boolean backStateIsReject() { + if (flowRecord == null) { + return false; + } long preId = flowRecord.getPreId(); if (preId == 0) { return false; @@ -201,6 +203,26 @@ public boolean isRejectState() { return false; } + /** + * 上级节点的状态是驳回状态 + * + * @see #backStateIsReject() + */ + @Deprecated + public boolean isRejectState() { + return this.backStateIsReject(); + } + + /** + * 当前节点的状态是驳回状态 + */ + public boolean currentStateIsReject() { + if (flowRecord != null) { + return flowRecord.getFlowSourceDirection() == FlowSourceDirection.REJECT; + } + return false; + } + /** * 预提交流程 diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 95efd861..41518c1b 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.20 + 2.9.21 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index ae099bac..417d26c0 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.20 + 2.9.21 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 24160f8e..481827bc 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.20 +CodingApi SpringBoot-Starter 2.9.21 springboot version (${spring-boot.version}) ------------------------------------------------------ From ab0d896eaae10c1475dd70b6c9447f813f654f6f Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 8 Jan 2025 16:47:23 +0800 Subject: [PATCH 080/129] update 2.9.22 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../codingapi/springboot/flow/service/FlowNodeService.java | 3 --- .../springboot/flow/service/impl/FlowSubmitService.java | 5 +++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- springboot-starter/src/main/resources/META-INF/banner.txt | 2 +- 9 files changed, 12 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index 66ed8121..113c8bd3 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.21 + 2.9.22 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index a27a5c21..3e4cdb54 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.21 + 2.9.22 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 58d364d6..23678969 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.21 + 2.9.22 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index cc0dfe6d..6ddcf793 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.21 + 2.9.22 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java index 4d3a092f..970bbb8d 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java @@ -253,9 +253,6 @@ private List createNextRecord() { if (customOperatorIds != null && !customOperatorIds.isEmpty()) { operators = operators.stream() .filter(operator -> customOperatorIds.contains(operator.getUserId())).collect(Collectors.toList()); - if (operators.size() != customOperatorIds.size()) { - throw new IllegalArgumentException("operator not match."); - } } List recordList; if (operators.isEmpty()) { diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index c63970e1..08cb15d7 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -370,6 +370,11 @@ public FlowSubmitResult trySubmitFlow() { this.loadNextNode(historyRecords); + while (nextNode.isCirculate()){ + flowNodeService.skipCirculate(); + this.nextNode = flowNodeService.getNextNode(); + } + List operators = flowNodeService.loadNextNodeOperators(); return new FlowSubmitResult(flowWork, nextNode, operators); } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 41518c1b..2a17b230 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.21 + 2.9.22 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 417d26c0..e17fb23e 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.21 + 2.9.22 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 481827bc..0a5dbd7a 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.21 +CodingApi SpringBoot-Starter 2.9.22 springboot version (${spring-boot.version}) ------------------------------------------------------ From c9524cebb23b3218f5fcb2c502303e42a0c2b101 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 10 Jan 2025 15:59:55 +0800 Subject: [PATCH 081/129] update 2.9.23 data authorization support union all sql --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- .../enhancer/DataPermissionSQLEnhancer.java | 24 ++++++++++++----- .../enhancer/TableColumnAliasHolder.java | 19 ++++++++++--- .../analyzer/SelectSQLAnalyzerTest.java | 27 +++++++++++++++++++ springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 10 files changed, 68 insertions(+), 16 deletions(-) diff --git a/pom.xml b/pom.xml index 113c8bd3..528c2cb2 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.22 + 2.9.23 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 3e4cdb54..f57c2c0f 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.22 + 2.9.23 springboot-starter-data-authorization diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java index 66a91a6b..3c39d992 100644 --- a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java @@ -8,12 +8,10 @@ import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Statement; -import net.sf.jsqlparser.statement.select.FromItem; -import net.sf.jsqlparser.statement.select.Join; -import net.sf.jsqlparser.statement.select.PlainSelect; -import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.select.*; import java.sql.SQLException; +import java.util.List; /** * 数据权限 SQL 增强器 @@ -45,8 +43,7 @@ public String getNewSQL() throws SQLException { if (statement instanceof Select) { tableColumnAliasHolder.holderAlias(); Select select = (Select) statement; - PlainSelect plainSelect = select.getPlainSelect(); - this.enhanceDataPermissionInSelect(plainSelect); + this.deepMatch(select); return statement.toString(); } } catch (Exception e) { @@ -55,6 +52,21 @@ public String getNewSQL() throws SQLException { return sql; } + + private void deepMatch(Select select) throws Exception { + if (select instanceof PlainSelect) { + PlainSelect plainSelect = select.getPlainSelect(); + this.enhanceDataPermissionInSelect(plainSelect); + } + if (select instanceof SetOperationList) { + SetOperationList setOperationList = select.getSetOperationList(); + List selectList = setOperationList.getSelects(); + for (Select selectItem : selectList) { + this.deepSearch(selectItem); + } + } } diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/analyzer/SelectSQLAnalyzerTest.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/analyzer/SelectSQLAnalyzerTest.java index ce2309f6..008062a5 100644 --- a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/analyzer/SelectSQLAnalyzerTest.java +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/analyzer/SelectSQLAnalyzerTest.java @@ -195,4 +195,31 @@ void test7() throws Exception{ System.out.println(builder.getNewSQL()); System.out.println(builder.getTableAlias());; } + + + @Test + @Order(8) + void test8() throws Exception{ + String sql = "select ade1_0.id,ade1_0.ba_dept_name,ade1_0.ba_org_shortname,ade1_0.ba_dept_code,ade1_0.ba_code,ade1_0.ba_dept_property_code,ade1_0.ba_parent_type,ade1_0.ba_real_super_org_id,ade1_0.ba_org_is_avoidance_dept,ade1_0.ba_real_super_org_id,ade1_0.ba_super_org_name " + + "from ba04_administrative_department ade1_0 where ade1_0.ba_parent_type=0" + + " union all select ade2_0.id,ade2_0.ba_dept_name,ade2_0.ba_org_shortname,ade2_0.ba_dept_code,ade2_0.ba_code,ade2_0.ba_dept_property_code,ade2_0.ba_parent_type,ade2_0.ba_real_super_org_id,ade2_0.ba_org_is_avoidance_dept,ade3_0.ba_real_super_org_id,ade3_0.ba_super_org_name" + + " from ba04_administrative_department ade2_0 left join ba04_administrative_department ade3_0 on ade2_0.ba_real_super_org_id=ade3_0.id " + + "where ade2_0.ba_real_super_org_id=1"; + + + + RowHandler rowHandler = (subSql, tableName, tableAlias) -> { + if (tableName.equalsIgnoreCase("ba04_administrative_department")) { + String conditionTemplate = "%s.id < 100 "; + return Condition.formatCondition(conditionTemplate, tableAlias); + } + return null; + }; + DataPermissionSQLEnhancer builder = new DataPermissionSQLEnhancer(sql, rowHandler); + String newSQL = builder.getNewSQL(); + System.out.println(newSQL); + System.out.println(builder.getTableAlias()); + assertEquals("SELECT ade1_0.id, ade1_0.ba_dept_name, ade1_0.ba_org_shortname, ade1_0.ba_dept_code, ade1_0.ba_code, ade1_0.ba_dept_property_code, ade1_0.ba_parent_type, ade1_0.ba_real_super_org_id, ade1_0.ba_org_is_avoidance_dept, ade1_0.ba_real_super_org_id, ade1_0.ba_super_org_name FROM ba04_administrative_department ade1_0 WHERE ade1_0.id < 100 AND ade1_0.ba_parent_type = 0 " + + "UNION ALL SELECT ade2_0.id, ade2_0.ba_dept_name, ade2_0.ba_org_shortname, ade2_0.ba_dept_code, ade2_0.ba_code, ade2_0.ba_dept_property_code, ade2_0.ba_parent_type, ade2_0.ba_real_super_org_id, ade2_0.ba_org_is_avoidance_dept, ade3_0.ba_real_super_org_id, ade3_0.ba_super_org_name FROM ba04_administrative_department ade2_0 LEFT JOIN ba04_administrative_department ade3_0 ON ade2_0.ba_real_super_org_id = ade3_0.id WHERE ade3_0.id < 100 AND ade2_0.id < 100 AND ade2_0.ba_real_super_org_id = 1", newSQL); + } } diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 23678969..6e549ff0 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.22 + 2.9.23 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 6ddcf793..075ee22c 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.22 + 2.9.23 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 2a17b230..973d3a01 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.22 + 2.9.23 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index e17fb23e..36352276 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.22 + 2.9.23 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 0a5dbd7a..e8ad2dcd 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.22 +CodingApi SpringBoot-Starter 2.9.23 springboot version (${spring-boot.version}) ------------------------------------------------------ From 7d0b79e6c7817b0e48b27fd573fb8de62ed71e8a Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 20 Jan 2025 17:53:28 +0800 Subject: [PATCH 082/129] update 2.9.24 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../java/com/codingapi/springboot/flow/pojo/FlowResult.java | 6 ++++++ .../com/codingapi/springboot/flow/record/FlowRecord.java | 4 ++++ .../springboot/flow/service/impl/FlowSubmitService.java | 4 ++-- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- springboot-starter/src/main/resources/META-INF/banner.txt | 2 +- 10 files changed, 19 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 528c2cb2..419db6b2 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.23 + 2.9.24 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index f57c2c0f..147c2962 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.23 + 2.9.24 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 6e549ff0..9e2bee2b 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.23 + 2.9.24 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 075ee22c..1c87e1bb 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.23 + 2.9.24 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java index ad65b649..2f2c4b8b 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java @@ -35,4 +35,10 @@ public FlowResult(FlowWork flowWork,FlowRecord flowRecord) { public List matchRecordByOperator(IFlowOperator operator){ return records.stream().filter(record -> record.isOperator(operator)).collect(Collectors.toList()); } + + + public boolean isOver() { + return records.stream().allMatch(FlowRecord::isOverNode); + } + } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java index 81dbef11..58e79ecc 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -432,4 +432,8 @@ public boolean isPostponed() { public boolean isStartRecord() { return this.preId == 0; } + + public boolean isOverNode() { + return this.nodeCode.equals(FlowNode.CODE_OVER); + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index 08cb15d7..3b80261f 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -231,13 +231,13 @@ private void pushEvent(FlowRecord flowRecord, int eventState) { */ public FlowResult submitFlow() { FlowResult flowResult = this.submitCurrentFlow(); - if (this.isSkipIfSameApprover()) { + if (this.isSkipIfSameApprover() && !flowResult.isOver()) { List flowRecords = flowResult.matchRecordByOperator(currentOperator); FlowResult result = flowResult; if (!flowRecords.isEmpty()) { for (FlowRecord flowRecord : flowRecords) { FlowSubmitService flowSubmitService = new FlowSubmitService(flowRecord.getId(), currentOperator, bindData, opinion, flowServiceRepositoryHolder); - result = flowSubmitService.submitCurrentFlow(); + result = flowSubmitService.submitFlow(); } } return result; diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 973d3a01..7e5727ee 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.23 + 2.9.24 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 36352276..5642dddc 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.23 + 2.9.24 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index e8ad2dcd..aa3f2d44 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.23 +CodingApi SpringBoot-Starter 2.9.24 springboot version (${spring-boot.version}) ------------------------------------------------------ From ef2700212021a2bd6f9ae7867c75f8d6ac7f5e03 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 21 Jan 2025 11:46:33 +0800 Subject: [PATCH 083/129] update 2.9.25 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/em/FlowButtonType.java | 2 + .../repository/FlowProcessRepository.java | 3 + .../flow/repository/FlowRecordRepository.java | 6 ++ .../springboot/flow/service/FlowService.java | 12 +++ .../flow/service/impl/FlowRemoveService.java | 58 +++++++++++++++ .../repository/FlowProcessRepositoryImpl.java | 5 +- .../repository/FlowRecordRepositoryImpl.java | 5 ++ .../springboot/flow/test/FlowTest.java | 74 +++++++++++++++++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 15 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java diff --git a/pom.xml b/pom.xml index 419db6b2..59321c51 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.24 + 2.9.25 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 147c2962..7a605c60 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.24 + 2.9.25 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 9e2bee2b..da743344 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.24 + 2.9.25 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 1c87e1bb..57fc064a 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.24 + 2.9.25 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowButtonType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowButtonType.java index 0fc7c71e..550766f9 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowButtonType.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowButtonType.java @@ -26,4 +26,6 @@ public enum FlowButtonType { CUSTOM, // 前端 VIEW, + // 删除 + REMOVE, } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java index 892141ea..acf8cfe1 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java @@ -13,4 +13,7 @@ public interface FlowProcessRepository { FlowWork getFlowWorkByProcessId(String processId); + + void deleteByProcessId(String processId); + } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java index 6948da3c..292d40e5 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java @@ -71,4 +71,10 @@ public interface FlowRecordRepository { */ void delete(List childrenRecords); + /** + * 根据流程id删除流程记录 + * @param processId 流程id + */ + void deleteByProcessId(String processId); + } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index a9aa8d13..e70ff123 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -22,6 +22,7 @@ public class FlowService { private final FlowDetailService flowDetailService; private final FlowCustomEventService flowCustomEventService; private final FlowRecallService flowRecallService; + private final FlowRemoveService flowRemoveService; private final FlowSaveService flowSaveService; private final FlowTransferService flowTransferService; private final FlowPostponedService flowPostponedService; @@ -40,6 +41,7 @@ public FlowService(FlowWorkRepository flowWorkRepository, this.flowDetailService = new FlowDetailService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository); this.flowCustomEventService = new FlowCustomEventService(flowWorkRepository,flowRecordRepository, flowProcessRepository); this.flowRecallService = new FlowRecallService(flowWorkRepository,flowRecordRepository, flowProcessRepository); + this.flowRemoveService = new FlowRemoveService(flowWorkRepository,flowRecordRepository, flowProcessRepository); this.flowSaveService = new FlowSaveService(flowWorkRepository,flowRecordRepository, flowBindDataRepository, flowProcessRepository); this.flowTransferService = new FlowTransferService(flowWorkRepository,flowRecordRepository, flowBindDataRepository, flowProcessRepository); this.flowPostponedService = new FlowPostponedService(flowWorkRepository,flowRecordRepository, flowProcessRepository); @@ -239,4 +241,14 @@ public void recall(long recordId, IFlowOperator currentOperator) { } + + /** + * 删除流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public void remove(long recordId, IFlowOperator currentOperator) { + flowRemoveService.remove(recordId, currentOperator); + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java new file mode 100644 index 00000000..82c42198 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java @@ -0,0 +1,58 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; +import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collections; +import java.util.List; + +@Transactional +@AllArgsConstructor +public class FlowRemoveService { + + private final FlowWorkRepository flowWorkRepository; + private final FlowRecordRepository flowRecordRepository; + private final FlowProcessRepository flowProcessRepository; + + + /** + * 删除流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public void remove(long recordId, IFlowOperator currentOperator) { + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService( + flowWorkRepository, + flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + + flowRecordVerifyService.verifyFlowRecordCurrentOperator(); + flowRecordVerifyService.loadFlowWork(); + flowRecordVerifyService.loadFlowNode(); + flowRecordVerifyService.verifyFlowRecordNotFinish(); + flowRecordVerifyService.verifyFlowRecordIsTodo(); + FlowNode flowNode = flowRecordVerifyService.getFlowNode(); + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); + + if(!flowNode.isStartNode()){ + throw new IllegalArgumentException("flow record not remove"); + } + + flowProcessRepository.deleteByProcessId(flowRecord.getProcessId()); + + flowRecordRepository.deleteByProcessId(flowRecord.getProcessId()); + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java index 782f0bae..b128f599 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java @@ -35,5 +35,8 @@ public FlowWork getFlowWorkByProcessId(String processId) { return flowBackup.resume(userRepository); } - + @Override + public void deleteByProcessId(String processId) { + cache.removeIf(flowProcess -> flowProcess.getProcessId().equals(processId)); + } } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java index 02d88d4b..59f60d7b 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java @@ -161,4 +161,9 @@ public void finishFlowRecordByProcessId(String processId) { public void delete(List childrenRecords) { cache.removeAll(childrenRecords); } + + @Override + public void deleteByProcessId(String processId) { + cache.removeIf(record -> record.getProcessId().equals(processId)); + } } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java index 9a8b88ec..9135b6ba 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java @@ -893,6 +893,80 @@ void recallTest1() { } + + /** + * 删除流程测试 + */ + @Test + void removeTest1() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),lorne.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + + FlowSubmitResult flowSubmitResult = flowService.trySubmitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + assertEquals(flowSubmitResult.getOperators().size(), 2); + assertTrue(flowSubmitResult.getOperators().stream().map(IFlowOperator::getUserId).collect(Collectors.toList()).contains(dept.getUserId())); + assertTrue(flowSubmitResult.getOperators().stream().map(IFlowOperator::getUserId).collect(Collectors.toList()).contains(lorne.getUserId())); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(dept.getUserId())); + + + // 撤销流程 + flowService.recall(userTodo.getId(), user); + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(1, records.size()); + + flowService.remove(userTodo.getId(), user); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(0, records.size()); + + } + + /** * 撤销流程测试 */ diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 7e5727ee..338f30fb 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.24 + 2.9.25 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 5642dddc..ec83d4aa 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.24 + 2.9.25 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index aa3f2d44..8b1b3b74 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.24 +CodingApi SpringBoot-Starter 2.9.25 springboot version (${spring-boot.version}) ------------------------------------------------------ From 26b650c6ac3b637f2c4266459ec9ddc8237060bb Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 21 Jan 2025 17:29:50 +0800 Subject: [PATCH 084/129] update 2.9.26 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/pojo/FlowStepResult.java | 28 +++++++ .../springboot/flow/service/FlowService.java | 13 +++ .../flow/service/impl/FlowStepService.java | 83 +++++++++++++++++++ .../springboot/flow/test/CirculateTest.java | 5 ++ .../springboot/flow/test/FlowTest.java | 6 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 12 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java diff --git a/pom.xml b/pom.xml index 59321c51..24174851 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.25 + 2.9.26 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 7a605c60..f6c5a124 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.25 + 2.9.26 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index da743344..1d3ee0a9 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.25 + 2.9.26 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 57fc064a..4de98f22 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.25 + 2.9.26 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java new file mode 100644 index 00000000..1ce8100b --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java @@ -0,0 +1,28 @@ +package com.codingapi.springboot.flow.pojo; + +import com.codingapi.springboot.flow.domain.FlowNode; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +@Getter +public class FlowStepResult { + + private final List flowNodes; + + public FlowStepResult() { + this.flowNodes = new ArrayList<>(); + } + + public void addFlowNode(FlowNode flowNode) { + this.flowNodes.add(flowNode); + } + + + public void print(){ + for (FlowNode flowNode : flowNodes) { + System.out.println("flowNode = " + flowNode.getName()); + } + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index e70ff123..838e26a4 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -4,6 +4,7 @@ import com.codingapi.springboot.flow.domain.Opinion; import com.codingapi.springboot.flow.pojo.FlowDetail; import com.codingapi.springboot.flow.pojo.FlowResult; +import com.codingapi.springboot.flow.pojo.FlowStepResult; import com.codingapi.springboot.flow.pojo.FlowSubmitResult; import com.codingapi.springboot.flow.repository.*; import com.codingapi.springboot.flow.result.MessageResult; @@ -188,6 +189,18 @@ public FlowSubmitResult trySubmitFlow(long recordId, IFlowOperator currentOperat } + /** + * 获取流程执行节点 + * + * @param workCode + * @param currentOperator + * @return + */ + public FlowStepResult getFlowStep(String workCode, IBindData bindData, IFlowOperator currentOperator) { + FlowStepService flowStepService = new FlowStepService(workCode, currentOperator, bindData, flowServiceRepositoryHolder); + return flowStepService.getFlowStep(); + } + /** * 尝试提交流程 (发起流程) * diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java new file mode 100644 index 00000000..5da4bba1 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java @@ -0,0 +1,83 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.pojo.FlowStepResult; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowOperatorRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.service.FlowNodeService; +import com.codingapi.springboot.flow.service.FlowServiceRepositoryHolder; +import com.codingapi.springboot.flow.user.IFlowOperator; + +import java.util.ArrayList; +import java.util.List; + +public class FlowStepService { + private final FlowWork flowWork; + + private final IFlowOperator currentOperator; + private final IBindData bindData; + private final FlowServiceRepositoryHolder flowServiceRepositoryHolder; + + private FlowNodeService flowNodeService; + private FlowNode flowNode; + + public FlowStepService(String workCode, IFlowOperator currentOperator, IBindData bindData, FlowServiceRepositoryHolder flowServiceRepositoryHolder) { + this.currentOperator = currentOperator; + this.bindData = bindData; + this.flowServiceRepositoryHolder = flowServiceRepositoryHolder; + this.flowWork = flowServiceRepositoryHolder.getFlowWorkRepository().getFlowWorkByCode(workCode); + } + + + public FlowStepResult getFlowStep() { + FlowStepResult flowStepResult = new FlowStepResult(); + // 获取开始节点 + FlowNode start = flowWork.getStartNode(); + if (start == null) { + throw new IllegalArgumentException("start node not found"); + } + + this.flowNode = start; + // 设置开始流程的上一个流程id + long preId = 0; + + // 创建流程id + String processId = "flow_" + System.currentTimeMillis(); + + List historyRecords = new ArrayList<>(); + + FlowOperatorRepository flowOperatorRepository = flowServiceRepositoryHolder.getFlowOperatorRepository(); + FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + + BindDataSnapshot snapshot = new BindDataSnapshot(bindData); + flowNodeService = new FlowNodeService(flowOperatorRepository, + flowRecordRepository, + snapshot, + Opinion.pass("同意"), + currentOperator, + currentOperator, + historyRecords, + flowWork, + null, + processId, + preId); + + flowNodeService.setNextNode(start); + + this.flowNode = start; + flowStepResult.addFlowNode(this.flowNode); + + do { + flowNodeService.loadNextPassNode(this.flowNode); + this.flowNode = flowNodeService.getNextNode(); + flowStepResult.addFlowNode(this.flowNode); + } while (!flowNode.isOverNode()); + + return flowStepResult; + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/CirculateTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/CirculateTest.java index 7e198d49..1a1c72cc 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/CirculateTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/CirculateTest.java @@ -8,6 +8,7 @@ import com.codingapi.springboot.flow.flow.Leave; import com.codingapi.springboot.flow.matcher.OperatorMatcher; import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.pojo.FlowStepResult; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.*; import com.codingapi.springboot.flow.service.FlowService; @@ -79,6 +80,10 @@ void circulate(){ // 创建流程 flowService.startFlow(workCode, user, leave, "发起流程"); + + FlowStepResult result = flowService.getFlowStep(workCode, leave, user); + result.print(); + // 查看我的待办 List userTodos = flowRecordRepository.findUnReadByOperatorId(user.getUserId(), pageRequest).getContent(); assertEquals(1, userTodos.size()); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java index 9135b6ba..b2f90c6e 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java @@ -8,6 +8,7 @@ import com.codingapi.springboot.flow.flow.Leave; import com.codingapi.springboot.flow.matcher.OperatorMatcher; import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.pojo.FlowStepResult; import com.codingapi.springboot.flow.pojo.FlowSubmitResult; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.*; @@ -72,6 +73,9 @@ void entrustTest() { Leave leave = new Leave("我要出去看看"); leaveRepository.save(leave); + FlowStepResult result = flowService.getFlowStep(workCode, leave, user); + result.print(); + // 创建流程 flowService.startFlow(workCode, user, leave, "发起流程"); @@ -898,7 +902,7 @@ void recallTest1() { * 删除流程测试 */ @Test - void removeTest1() { + void removeTest() { PageRequest pageRequest = PageRequest.of(0, 1000); User lorne = new User("lorne"); diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 338f30fb..3226f4b8 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.25 + 2.9.26 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index ec83d4aa..ff2152f6 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.25 + 2.9.26 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 8b1b3b74..c29a01a4 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.25 +CodingApi SpringBoot-Starter 2.9.26 springboot version (${spring-boot.version}) ------------------------------------------------------ From b89eddea183bcf37cbb3b9adf1856b67c487e846 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 22 Jan 2025 11:31:52 +0800 Subject: [PATCH 085/129] update 2.9.27 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/pojo/FlowStepResult.java | 28 ++++++++++++++++--- .../flow/service/impl/FlowStepService.java | 4 +-- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 9 files changed, 33 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index 24174851..aae2e4a0 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.26 + 2.9.27 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index f6c5a124..6bbb7eb2 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.26 + 2.9.27 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 1d3ee0a9..549d6bbb 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.26 + 2.9.27 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 4de98f22..e971e4da 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.26 + 2.9.27 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java index 1ce8100b..36d49c36 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java @@ -1,6 +1,8 @@ package com.codingapi.springboot.flow.pojo; import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.em.NodeType; +import com.codingapi.springboot.flow.user.IFlowOperator; import lombok.Getter; import java.util.ArrayList; @@ -9,20 +11,38 @@ @Getter public class FlowStepResult { - private final List flowNodes; + private final List flowNodes; public FlowStepResult() { this.flowNodes = new ArrayList<>(); } - public void addFlowNode(FlowNode flowNode) { - this.flowNodes.add(flowNode); + public void addFlowNode(FlowNode flowNode,List operators) { + this.flowNodes.add(new FlowStepNode(flowNode.getId(), flowNode.getCode(),flowNode.getName(),flowNode.getType(),operators)); } public void print(){ - for (FlowNode flowNode : flowNodes) { + for (FlowStepNode flowNode : flowNodes) { System.out.println("flowNode = " + flowNode.getName()); } } + + + @Getter + public static class FlowStepNode{ + private final String id; + private final String code; + private final String name; + private final NodeType type; + private final List operators; + + public FlowStepNode(String id, String code, String name, NodeType type,List operators) { + this.id = id; + this.code = code; + this.name = name; + this.type = type; + this.operators = operators; + } + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java index 5da4bba1..c03833dd 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java @@ -70,12 +70,12 @@ public FlowStepResult getFlowStep() { flowNodeService.setNextNode(start); this.flowNode = start; - flowStepResult.addFlowNode(this.flowNode); + flowStepResult.addFlowNode(this.flowNode, this.flowNodeService.loadNextNodeOperators()); do { flowNodeService.loadNextPassNode(this.flowNode); this.flowNode = flowNodeService.getNextNode(); - flowStepResult.addFlowNode(this.flowNode); + flowStepResult.addFlowNode(this.flowNode, this.flowNodeService.loadNextNodeOperators()); } while (!flowNode.isOverNode()); return flowStepResult; diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 3226f4b8..f0a652d9 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.26 + 2.9.27 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index ff2152f6..faedd760 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.26 + 2.9.27 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index c29a01a4..8fc040be 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.26 +CodingApi SpringBoot-Starter 2.9.27 springboot version (${spring-boot.version}) ------------------------------------------------------ From a50655d8918ae9102a3e64a6d130efc76e751ee8 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 6 Feb 2025 10:19:25 +0800 Subject: [PATCH 086/129] update 2.9.28 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/domain/FlowNode.java | 5 +- .../springboot/flow/domain/Opinion.java | 11 +++ .../springboot/flow/em/FlowType.java | 6 +- .../springboot/flow/record/FlowRecord.java | 7 ++ .../flow/service/FlowDirectionService.java | 3 +- .../flow/service/FlowNodeService.java | 6 +- .../springboot/flow/service/FlowService.java | 9 +++ .../flow/service/impl/FlowNotifyService.java | 81 +++++++++++++++++++ .../flow/service/impl/FlowSubmitService.java | 8 +- .../springboot/flow/test/FlowTest2.java | 70 +++++++++++++++- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 17 files changed, 201 insertions(+), 19 deletions(-) create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowNotifyService.java diff --git a/pom.xml b/pom.xml index aae2e4a0..baf5281c 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.27 + 2.9.28 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 6bbb7eb2..005e64de 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.27 + 2.9.28 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 549d6bbb..69b87a9b 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.27 + 2.9.28 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index e971e4da..9fee697b 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.27 + 2.9.28 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java index 37bc95ec..1e9985fb 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java @@ -217,7 +217,8 @@ public FlowRecord createRecord(long workId, String title, IFlowOperator createOperator, IFlowOperator currentOperator, - BindDataSnapshot snapshot) { + BindDataSnapshot snapshot, + boolean isWaiting) { // 当前操作者存在委托人时,才需要寻找委托人 IFlowOperator flowOperator = currentOperator; @@ -239,7 +240,7 @@ public FlowRecord createRecord(long workId, record.setPreId(preId); record.setTitle(title); record.setTimeoutTime(this.loadTimeoutTime()); - record.setFlowType(FlowType.TODO); + record.setFlowType(isWaiting?FlowType.WAITING:FlowType.TODO); record.setErrMessage(null); record.setSnapshotId(snapshot.getId()); return record; diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java index 2c1dc8f0..f9f72e78 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java @@ -33,6 +33,9 @@ public class Opinion { public static final int RESULT_REJECT = 3; // 审批结果 抄送 public static final int RESULT_CIRCULATE = 4; + // 审批结果 等待 + public static final int RESULT_WAITING = 5; + /** * 审批意见 @@ -88,6 +91,10 @@ public static Opinion transfer(String advice) { return new Opinion(advice, RESULT_TRANSFER, TYPE_DEFAULT); } + public static Opinion waiting(String advice) { + return new Opinion(advice, RESULT_WAITING, TYPE_DEFAULT); + } + public static Opinion unSignAutoSuccess() { return new Opinion("非会签自动审批", RESULT_PASS, TYPE_AUTO); } @@ -104,6 +111,10 @@ public boolean isSuccess() { return result == RESULT_PASS; } + public boolean isWaiting() { + return result == RESULT_WAITING; + } + public boolean isReject() { return result == RESULT_REJECT; } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java index 79b54d00..5e36e57b 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java @@ -20,7 +20,11 @@ public enum FlowType { /** * 转办 */ - TRANSFER; + TRANSFER, + /** + * 等待执行 + */ + WAITING; public static FlowType parser(String type){ diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java index 58e79ecc..8c1aef89 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -321,6 +321,13 @@ public boolean isFinish() { return this.flowStatus == FlowStatus.FINISH; } + /** + * 是否等待 + */ + public boolean isWaiting() { + return this.flowType == FlowType.WAITING; + } + /** * 是否是待办 */ diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java index 829238bb..fb925dff 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java @@ -40,7 +40,7 @@ public void bindHistoryRecords(List historyRecords) { * 解析当前的审批方向 */ public void loadFlowSourceDirection() { - if (opinion.isSuccess()) { + if (opinion.isSuccess() || opinion.isWaiting()) { flowSourceDirection = FlowSourceDirection.PASS; } if (opinion.isReject()) { @@ -48,7 +48,6 @@ public void loadFlowSourceDirection() { } } - /** * 重新加载审批方向 * 根据会签结果判断是否需要重新设置审批方向 diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java index 970bbb8d..75bdf395 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java @@ -264,7 +264,7 @@ private List createNextRecord() { String recordTitle = nextNode.generateTitle(flowSession); recordList = new ArrayList<>(); for (IFlowOperator operator : operators) { - FlowRecord record = nextNode.createRecord(workId, flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot); + FlowRecord record = nextNode.createRecord(workId, flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot, opinion.isWaiting()); recordList.add(record); } } @@ -294,7 +294,7 @@ private List errMatcher(FlowNode currentNode, IFlowOperator currentO for (IFlowOperator operator : operators) { FlowSession content = new FlowSession(flowRecord, flowWork, currentNode, createOperator, operator, snapshot.toBindData(), opinion, historyRecords); String recordTitle = currentNode.generateTitle(content); - FlowRecord record = currentNode.createRecord(flowWork.getId(), flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot); + FlowRecord record = currentNode.createRecord(flowWork.getId(), flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot, opinion.isWaiting()); recordList.add(record); } return recordList; @@ -312,7 +312,7 @@ private List errMatcher(FlowNode currentNode, IFlowOperator currentO if (!matcherOperators.isEmpty()) { for (IFlowOperator matcherOperator : matcherOperators) { String recordTitle = node.generateTitle(content); - FlowRecord record = node.createRecord(flowWork.getId(), flowWork.getCode(), processId, preId, recordTitle, createOperator, matcherOperator, snapshot); + FlowRecord record = node.createRecord(flowWork.getId(), flowWork.getCode(), processId, preId, recordTitle, createOperator, matcherOperator, snapshot, opinion.isWaiting()); recordList.add(record); } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index 838e26a4..0aaa054c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -228,6 +228,15 @@ public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBind return flowSubmitService.submitFlow(); } + /** + * 唤醒流程 + * @param processId 流程实例id + * @param currentOperator 当前操作者 + */ + public void notifyFlow(String processId,IFlowOperator currentOperator) { + FlowNotifyService flowNotifyService = new FlowNotifyService(processId, currentOperator, flowServiceRepositoryHolder); + flowNotifyService.notifyFlow(); + } /** * 自定义事件 diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowNotifyService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowNotifyService.java new file mode 100644 index 00000000..53d11750 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowNotifyService.java @@ -0,0 +1,81 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.em.FlowType; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowBindDataRepository; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; +import com.codingapi.springboot.flow.service.FlowServiceRepositoryHolder; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@Transactional +public class FlowNotifyService { + + private final String processId; + private final IFlowOperator currentOperator; + private final FlowRecordRepository flowRecordRepository; + private final FlowBindDataRepository flowBindDataRepository; + private final FlowWorkRepository flowWorkRepository; + private final FlowProcessRepository flowProcessRepository; + + + public FlowNotifyService(String processId, IFlowOperator currentOperator, FlowServiceRepositoryHolder flowServiceRepositoryHolder) { + this.processId = processId; + this.currentOperator = currentOperator; + this.flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + this.flowBindDataRepository = flowServiceRepositoryHolder.getFlowBindDataRepository(); + this.flowWorkRepository = flowServiceRepositoryHolder.getFlowWorkRepository(); + this.flowProcessRepository = flowServiceRepositoryHolder.getFlowProcessRepository(); + } + + + /** + * 获取流程设计对象 + */ + public FlowWork loadFlowWork(FlowRecord flowRecord) { + FlowWork flowWork = flowProcessRepository.getFlowWorkByProcessId(flowRecord.getProcessId()); + if (flowWork == null) { + flowWork = flowWorkRepository.getFlowWorkByCode(flowRecord.getWorkCode()); + } + if (flowWork == null) { + throw new IllegalArgumentException("flow work not found"); + } + flowWork.enableValidate(); + + return flowWork; + } + + /** + * 流程通知 + */ + public void notifyFlow() { + List flowRecords = flowRecordRepository.findFlowRecordByProcessId(processId); + List waitingRecords = flowRecords.stream().filter(FlowRecord::isWaiting).collect(Collectors.toList()); + for (FlowRecord flowRecord : waitingRecords) { + if (flowRecord.isOperator(currentOperator)) { + flowRecord.setFlowType(FlowType.TODO); + flowRecordRepository.update(flowRecord); + + BindDataSnapshot snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + + FlowWork flowWork = this.loadFlowWork(flowRecord); + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_TODO, + flowRecord, + flowRecord.getCurrentOperator(), + flowWork, + snapshot.toBindData() + ), true); + } + } + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index 3b80261f..4f58d0d0 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -209,7 +209,7 @@ private void updateFinishFlowRecord() { } // 保存流程记录 - private void saveFlowRecords(List flowRecords) { + private void saveNextFlowRecords(List flowRecords) { flowServiceRepositoryHolder.getFlowRecordRepository().save(flowRecords); } @@ -313,7 +313,7 @@ private FlowResult submitCurrentFlow() { } // 保存流程记录 - this.saveFlowRecords(nextRecords); + this.saveNextFlowRecords(nextRecords); // 推送审批事件消息 int eventState = flowSourceDirection == FlowSourceDirection.PASS ? FlowApprovalEvent.STATE_PASS : FlowApprovalEvent.STATE_REJECT; @@ -321,7 +321,9 @@ private FlowResult submitCurrentFlow() { // 推送待办事件消息 for (FlowRecord record : nextRecords) { - this.pushEvent(record, FlowApprovalEvent.STATE_TODO); + if(record.isTodo()) { + this.pushEvent(record, FlowApprovalEvent.STATE_TODO); + } } return new FlowResult(flowWork, nextRecords); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java index 7321f63c..a420e03a 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java @@ -30,7 +30,7 @@ public class FlowTest2 { private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository,flowProcessRepository,flowBackupRepository); /** - * flow test + * 转办测试 */ @Test void flowTest() { @@ -107,4 +107,72 @@ void flowTest() { assertTrue(records.stream().allMatch(FlowRecord::isFinish)); } + + + /** + * 流程等待测试 + */ + @Test + void flowWaitingTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + User lorne = new User("lorne"); + userRepository.save(lorne); + + User boss = new User("boss"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(lorne) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("老板审批", "boss", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("老板审批", "start", "boss") + .relation("结束节点", "boss", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我想要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, lorne, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + String processId = userTodos.get(0).getProcessId(); + + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), lorne, leave, Opinion.waiting("自己先提交")); + + // 查看boss的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(0, bossTodos.size()); + + // 通知流程 + flowService.notifyFlow(processId,boss); + + // 查看boss的待办 + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("领导审批通过")); + + bossTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(0, bossTodos.size()); + + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(2, records.size()); + + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + } } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index f0a652d9..934dd494 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.27 + 2.9.28 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index faedd760..4393952f 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.27 + 2.9.28 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 8fc040be..3ca43830 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.27 +CodingApi SpringBoot-Starter 2.9.28 springboot version (${spring-boot.version}) ------------------------------------------------------ From 9ede2520482ff60eeb8f6eb2d7bf7c585c1a43bf Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 10 Feb 2025 09:39:21 +0800 Subject: [PATCH 087/129] update 2.9.29 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/content/FlowSession.java | 4 +- .../springboot/flow/record/FlowRecord.java | 8 ++ .../flow/service/FlowNodeService.java | 54 ++++++--- .../flow/service/impl/FlowSubmitService.java | 2 +- .../springboot/flow/test/FlowTest2.java | 113 ++++++++++++++++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 12 files changed, 168 insertions(+), 27 deletions(-) diff --git a/pom.xml b/pom.xml index baf5281c..bc9da7e4 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.28 + 2.9.29 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 005e64de..4e627f67 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.28 + 2.9.29 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 69b87a9b..acb0a010 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.28 + 2.9.29 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 9fee697b..9a1528d2 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.28 + 2.9.29 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java index 7d8accd4..60f94ae5 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java @@ -24,7 +24,7 @@ @Getter public class FlowSession { - // 当前的流程记录 + // 当前的流程记录(当前审批的流程) private final FlowRecord flowRecord; // 当前的流程设计器 private final FlowWork flowWork; @@ -32,7 +32,7 @@ public class FlowSession { private final FlowNode flowNode; // 流程的创建者 private final IFlowOperator createOperator; - // 当前的操作者 + // 当前的操作者(当前的操作者,非代办人) private final IFlowOperator currentOperator; // 流程绑定数据 private final IBindData bindData; diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java index 8c1aef89..95b1a39b 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -344,6 +344,14 @@ public boolean isTransfer() { return this.flowType == FlowType.TRANSFER; } + + /** + * 拒绝状态 + */ + public boolean isReject() { + return this.opinion != null && this.opinion.isReject() && isDone(); + } + /** * 审批通过 */ diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java index 75bdf395..ba755514 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java @@ -101,24 +101,44 @@ public void skipCirculate() { /** * 加载默认回退节点 */ - public void loadDefaultBackNode(long parentRecordId) { - IFlowOperator flowOperator; - // 拒绝时,默认返回上一个已办节点 - FlowRecord preRecord = flowRecordRepository.getFlowRecordById(parentRecordId); - // 只寻找已办节点 - while (!preRecord.isDone()) { - // 继续寻找上一个节点 - preRecord = flowRecordRepository.getFlowRecordById(preRecord.getPreId()); - } - // 获取上一个节点的审批者,继续将审批者设置为当前审批者 - flowOperator = preRecord.getCurrentOperator(); - FlowNode nextNode = flowWork.getNodeByCode(preRecord.getNodeCode()); - if (nextNode == null) { - throw new IllegalArgumentException("next node not found"); + public void loadDefaultBackNode(FlowRecord currentRecord) { + List historyRecords = + flowRecordRepository.findFlowRecordByProcessId(currentRecord.getProcessId()) + .stream() + .sorted((o1, o2) -> (int) (o2.getId() - o1.getId())) + .filter(record -> record.getId() < currentRecord.getId()) + .collect(Collectors.toList()); + + int index = 0; + while (true) { + if (index >= historyRecords.size()) { + throw new IllegalArgumentException("back node not found"); + } + FlowRecord record = historyRecords.get(index); + if (record.isDone()) { + // 是连续的回退节点时,则根据流程记录的状态来判断 + if(record.isReject()){ + boolean startRemove = false; + for(FlowRecord historyRecord: historyRecords){ + if(startRemove){ + this.nextNode = flowWork.getNodeByCode(historyRecord.getNodeCode()); + this.nextOperator = historyRecord.getCurrentOperator(); + this.backOperator = historyRecord.getCurrentOperator(); + return; + } + if(historyRecord.getNodeCode().equals(currentRecord.getNodeCode())){ + startRemove = true; + } + } + }else { + this.nextNode = flowWork.getNodeByCode(record.getNodeCode()); + this.nextOperator = record.getCurrentOperator(); + this.backOperator = record.getCurrentOperator(); + return; + } + } + index++; } - this.nextNode = nextNode; - this.nextOperator = flowOperator; - this.backOperator = flowOperator; } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index 4f58d0d0..5b01e3b3 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -194,7 +194,7 @@ private void loadNextNode(List historyRecords) { flowNodeService.loadNextPassNode(flowNode); // 审批拒绝返回上一节点 } else if (flowDirectionService.isDefaultBackRecord()) { - flowNodeService.loadDefaultBackNode(flowRecord.getPreId()); + flowNodeService.loadDefaultBackNode(flowRecord); } else { // 审批拒绝,并且自定了返回节点 flowNodeService.loadCustomBackNode(flowNode, flowRecord.getPreId()); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java index a420e03a..f4f350a1 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java @@ -7,6 +7,7 @@ import com.codingapi.springboot.flow.em.ApprovalType; import com.codingapi.springboot.flow.flow.Leave; import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.pojo.FlowDetail; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.*; import com.codingapi.springboot.flow.service.FlowService; @@ -175,4 +176,116 @@ void flowWaitingTest() { assertTrue(records.stream().allMatch(FlowRecord::isFinish)); } + + + /** + * 部门拒绝再提交测试 + */ + @Test + void rejectTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + + // 查看流程详情 + FlowDetail flowDetail = flowService.detail(userTodo.getId()); + assertEquals("我要出去看看", ((Leave) flowDetail.getBindData()).getTitle()); + assertTrue(flowDetail.getFlowRecord().isUnRead()); + + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看老板审批 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 老板审批不通过 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.reject("不同意")); + + // 部门经理查看到流程 + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.reject("不同意")); + + // 查看用户的待办 + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 用户再次提交 + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 部门经理查看到流程 + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看老板审批 + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 老板审批通过 + bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(7, records.size()); + + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + } } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 934dd494..d546706f 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.28 + 2.9.29 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 4393952f..4b498635 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.28 + 2.9.29 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 3ca43830..cc3a14af 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.28 +CodingApi SpringBoot-Starter 2.9.29 springboot version (${spring-boot.version}) ------------------------------------------------------ From 48120b08a9b673c3e2a11e8ab90960f5ca306045 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 22 Feb 2025 16:09:39 +0800 Subject: [PATCH 088/129] update 2.9.30 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../springboot/fast/jpa/SQLBuilder.java | 16 ++++++++++++++++ springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 8 files changed, 23 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index bc9da7e4..8332e528 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.29 + 2.9.30 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 4e627f67..9b772721 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.29 + 2.9.30 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index acb0a010..36ad9e09 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.29 + 2.9.30 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java index 0eaaf2e4..020e2802 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java @@ -9,6 +9,7 @@ public class SQLBuilder { private final StringBuilder sqlBuilder; private final StringBuilder countSQLBuilder; + @Getter private int index; private final List params; @Getter @@ -39,6 +40,21 @@ public void append(String sql, Object value) { } } + public void addParam(Object value){ + params.add(value); + index++; + } + + public void addParam(Object value,int index){ + params.add(value); + this.index = index; + } + + public void appendSql(String sql){ + sqlBuilder.append(" ").append(sql).append(" "); + countSQLBuilder.append(" ").append(sql).append(" "); + } + public String getSQL() { return sqlBuilder.toString(); } diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 9a1528d2..197a1baf 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.29 + 2.9.30 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index d546706f..ccc8dcef 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.29 + 2.9.30 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 4b498635..9298754f 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.29 + 2.9.30 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index cc3a14af..70fefe7b 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.29 +CodingApi SpringBoot-Starter 2.9.30 springboot version (${spring-boot.version}) ------------------------------------------------------ From 78e5872c14defec9f416d93de062f1e8b86f52f4 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 24 Feb 2025 19:30:09 +0800 Subject: [PATCH 089/129] update 2.9.31 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/service/impl/FlowSubmitService.java | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- springboot-starter/src/main/resources/META-INF/banner.txt | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 8332e528..c15d5c31 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.30 + 2.9.31 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 9b772721..4fb46f7e 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.30 + 2.9.31 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 36ad9e09..47f3e5ba 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.30 + 2.9.31 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 197a1baf..fe460060 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.30 + 2.9.31 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index 5b01e3b3..69833b79 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -284,7 +284,7 @@ private FlowResult submitCurrentFlow() { if (record.isTodo() && record.getId() != flowRecord.getId()) { record.autoPass(currentOperator, snapshot); FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); - flowRecordRepository.update(flowRecord); + flowRecordRepository.update(record); } } } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index ccc8dcef..2ec3a47e 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.30 + 2.9.31 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 9298754f..ccd75aab 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.30 + 2.9.31 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 70fefe7b..92e6a74e 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.30 +CodingApi SpringBoot-Starter 2.9.31 springboot version (${spring-boot.version}) ------------------------------------------------------ From 53b8d7758ff572912623c36d242372efb7e890fd Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 12 Mar 2025 17:48:57 +0800 Subject: [PATCH 090/129] support search isNull isNotNull notIn --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../jpa/repository/DynamicSQLBuilder.java | 15 +++++ .../springboot/fast/DemoRepositoryTest.java | 63 ++++++++++++++++++- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/dto/request/Filter.java | 12 ++++ .../framework/dto/request/Relation.java | 3 + .../src/main/resources/META-INF/banner.txt | 2 +- 11 files changed, 98 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index c15d5c31..ef24153e 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.31 + 2.9.32 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 4fb46f7e..bc5b0971 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.31 + 2.9.32 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 47f3e5ba..44d89bce 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.31 + 2.9.32 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java index 68052924..50dc3b5b 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java @@ -99,6 +99,14 @@ private void buildSQL(Filter filter, StringBuilder hql) { paramIndex++; } + if (filter.isNull()) { + hql.append(filter.getKey()).append(" IS NULL "); + } + + if (filter.isNotNull()) { + hql.append(filter.getKey()).append(" IS NOT NULL "); + } + if (filter.isNotEqual()) { hql.append(filter.getKey()).append(" != ?").append(paramIndex); params.add(filter.getValue()[0]); @@ -125,6 +133,13 @@ private void buildSQL(Filter filter, StringBuilder hql) { params.add(Arrays.asList(filter.getValue())); paramIndex++; } + + if (filter.isNotIn()) { + hql.append(filter.getKey()).append(" NOT IN (").append("?").append(paramIndex).append(")"); + params.add(Arrays.asList(filter.getValue())); + paramIndex++; + } + if (filter.isGreaterThan()) { hql.append(filter.getKey()).append(" > ?").append(paramIndex); params.add(filter.getValue()[0]); diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index 236f1d51..09ca9cdc 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -56,6 +56,44 @@ void findAll() { assertEquals(1, page.getTotalElements()); } + @Test + void pageRequestIsNull() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demo1 = demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demoRepository.save(demo2); + + PageRequest request = new PageRequest(); + request.setCurrent(1); + request.setPageSize(10); + request.addFilter("name", Relation.IS_NULL); + + Page page = demoRepository.pageRequest(request); + assertEquals(1, page.getTotalElements()); + } + + @Test + void pageRequestIsNotNull() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demo1 = demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demoRepository.save(demo2); + + PageRequest request = new PageRequest(); + request.setCurrent(1); + request.setPageSize(10); + request.addFilter("name", Relation.IS_NOT_NULL); + + Page page = demoRepository.pageRequest(request); + assertEquals(1, page.getTotalElements()); + } + @Test void pageRequestNotEqual() { demoRepository.deleteAll(); @@ -115,8 +153,29 @@ void customInSearch() { request.addFilter("id", Relation.IN, 1, 2, 3); Page page = demoRepository.pageRequest(request); - log.info("demo:{}", page.getContent()); -// assertEquals(2, page.getTotalElements()); + assertEquals(2, page.getTotalElements()); + } + + + @Test + void customNotInSearch() { + demoRepository.deleteAll(); + Demo demo1 = new Demo(); + demo1.setName("123"); + demoRepository.save(demo1); + + Demo demo2 = new Demo(); + demo2.setName("456"); + demoRepository.save(demo2); + + PageRequest request = new PageRequest(); + request.setCurrent(1); + request.setPageSize(10); + + request.addFilter("id", Relation.NOT_IN, 3); + + Page page = demoRepository.pageRequest(request); + assertEquals(2, page.getTotalElements()); } diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index fe460060..606d59de 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.31 + 2.9.32 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 2ec3a47e..cc4a5584 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.31 + 2.9.32 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index ccd75aab..8bacf8c0 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.31 + 2.9.32 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java index 319a916a..c7223a90 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java @@ -48,6 +48,18 @@ public boolean isEqual() { return relation == Relation.EQUAL; } + public boolean isNull() { + return relation == Relation.IS_NULL; + } + + public boolean isNotNull() { + return relation == Relation.IS_NOT_NULL; + } + + public boolean isNotIn() { + return relation == Relation.NOT_IN; + } + public boolean isNotEqual() { return relation == Relation.NOT_EQUAL; } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java index 0bd900dd..3fd9fce5 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java @@ -9,6 +9,9 @@ public enum Relation { RIGHT_LIKE, BETWEEN, IN, + NOT_IN, + IS_NULL, + IS_NOT_NULL, GREATER_THAN, LESS_THAN, GREATER_THAN_EQUAL, diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 92e6a74e..6a0d179e 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.31 +CodingApi SpringBoot-Starter 2.9.32 springboot version (${spring-boot.version}) ------------------------------------------------------ From 7debd6d6dced8c14a97947bf2136ceef4e3041b4 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 12 Mar 2025 17:55:56 +0800 Subject: [PATCH 091/129] support search isNull isNotNull notIn --- .../java/com/codingapi/springboot/fast/DemoRepositoryTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java index 09ca9cdc..9da2c24c 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/DemoRepositoryTest.java @@ -153,7 +153,7 @@ void customInSearch() { request.addFilter("id", Relation.IN, 1, 2, 3); Page page = demoRepository.pageRequest(request); - assertEquals(2, page.getTotalElements()); + System.out.println(page.getContent()); } From eb7e466706e5c8da0eb52792e65e6c172515c1fe Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 21 Mar 2025 20:39:23 +0800 Subject: [PATCH 092/129] fix version 2.9.33 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../flow/service/FlowDirectionService.java | 3 ++- .../springboot/flow/test/FlowTest2.java | 21 ++++++++++++------- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 9 files changed, 23 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index ef24153e..78179284 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.32 + 2.9.33 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index bc5b0971..66eb4aa3 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.32 + 2.9.33 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 44d89bce..cd7c58a8 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.32 + 2.9.33 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 606d59de..0857f71d 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.32 + 2.9.33 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java index fb925dff..367efa68 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java @@ -54,7 +54,8 @@ public void loadFlowSourceDirection() { */ public FlowSourceDirection reloadFlowSourceDirection() { if (flowNode.isSign()) { - boolean allPass = historyRecords.stream().filter(item -> !item.isTransfer()).allMatch(FlowRecord::isPass); + boolean allPass = historyRecords.stream().filter(item -> !item.isTransfer()) + .allMatch(item-> item.isPass() || item.getOpinion().isWaiting()); if (!allPass) { flowSourceDirection = FlowSourceDirection.REJECT; } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java index f4f350a1..7ea093dc 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java @@ -126,11 +126,13 @@ void flowWaitingTest() { .title("请假流程") .nodes() .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) - .node("老板审批", "boss", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("老板审批", "boss", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("老板审批", "boss1", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() .relation("老板审批", "start", "boss") - .relation("结束节点", "boss", "over") + .relation("老板审批1", "boss", "boss1") + .relation("结束节点", "boss1", "over") .build(); flowWorkRepository.save(flowWork); @@ -150,11 +152,17 @@ void flowWaitingTest() { String processId = userTodos.get(0).getProcessId(); FlowRecord userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), lorne, leave, Opinion.waiting("自己先提交")); + flowService.submitFlow(userTodo.getId(), lorne, leave, Opinion.pass("我提交了")); // 查看boss的待办 List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); - assertEquals(0, bossTodos.size()); + assertEquals(1, bossTodos.size()); + + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.waiting("我等待提交")); + + userTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); // 通知流程 flowService.notifyFlow(processId,boss); @@ -163,18 +171,17 @@ void flowWaitingTest() { bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); assertEquals(1, bossTodos.size()); - FlowRecord bossTodo = bossTodos.get(0); + bossTodo = bossTodos.get(0); flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("领导审批通过")); bossTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); assertEquals(0, bossTodos.size()); List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(2, records.size()); + assertEquals(3, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); - } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index cc4a5584..57a9f7b5 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.32 + 2.9.33 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 8bacf8c0..253f1adc 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.32 + 2.9.33 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 6a0d179e..2bcaa13c 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.32 +CodingApi SpringBoot-Starter 2.9.33 springboot version (${spring-boot.version}) ------------------------------------------------------ From b750706c77779239b20a1ba1c7bac08365d294e2 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 8 May 2025 10:09:20 +0800 Subject: [PATCH 093/129] update version to add skipDataAuthorization void method --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- .../interceptor/SQLRunningContext.java | 18 +++++++++++++++++- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 8 files changed, 24 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 78179284..347b26f9 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.33 + 2.9.34 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 66eb4aa3..43cb0bb9 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.33 + 2.9.34 springboot-starter-data-authorization diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLRunningContext.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLRunningContext.java index fab68f60..c22d4e25 100644 --- a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLRunningContext.java +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLRunningContext.java @@ -3,6 +3,7 @@ import lombok.Getter; import java.sql.SQLException; +import java.util.function.Supplier; /** * SQLRunningContext SQL执行拦截上下文 @@ -55,7 +56,7 @@ public SQLInterceptState intercept(String sql) throws SQLException { * @param T * @return T */ - public T skipDataAuthorization(java.util.function.Supplier supplier) { + public T skipDataAuthorization(Supplier supplier) { try { skipInterceptor.set(true); return (T) supplier.get(); @@ -64,4 +65,19 @@ public T skipDataAuthorization(java.util.function.Supplier supplier) { } } + + /** + * 跳过数据权限拦截 + * + * @param runnable 业务逻辑 + */ + public void skipDataAuthorization(Runnable runnable) { + try { + skipInterceptor.set(true); + runnable.run(); + } finally { + skipInterceptor.set(false); + } + } + } diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index cd7c58a8..d11dc629 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.33 + 2.9.34 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 0857f71d..1315c1ca 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.33 + 2.9.34 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 57a9f7b5..303fa950 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.33 + 2.9.34 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 253f1adc..c7913341 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.33 + 2.9.34 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 2bcaa13c..5efb14a2 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.33 +CodingApi SpringBoot-Starter 2.9.34 springboot version (${spring-boot.version}) ------------------------------------------------------ From d0c097eb507ba90971b6439c350b9c32e6635d62 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 14 May 2025 16:54:03 +0800 Subject: [PATCH 094/129] fix skipIfSameApprover reject bug --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/pojo/FlowResult.java | 3 + .../springboot/flow/record/FlowRecord.java | 4 + .../flow/service/impl/FlowSubmitService.java | 2 +- .../springboot/flow/test/FlowTest.java | 83 +++++++++++++++++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 11 files changed, 98 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 347b26f9..62a61994 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.34 + 2.9.35 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 43cb0bb9..394bb0d2 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.34 + 2.9.35 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index d11dc629..5410f3df 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.34 + 2.9.35 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 1315c1ca..1ad05ddf 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.34 + 2.9.35 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java index 2f2c4b8b..1a825418 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java @@ -41,4 +41,7 @@ public boolean isOver() { return records.stream().allMatch(FlowRecord::isOverNode); } + public boolean isStart() { + return records.stream().allMatch(FlowRecord::isStartNode); + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java index 95b1a39b..fbd303e8 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -451,4 +451,8 @@ public boolean isStartRecord() { public boolean isOverNode() { return this.nodeCode.equals(FlowNode.CODE_OVER); } + + public boolean isStartNode() { + return this.nodeCode.equals(FlowNode.CODE_START); + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index 69833b79..fd188fcd 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -231,7 +231,7 @@ private void pushEvent(FlowRecord flowRecord, int eventState) { */ public FlowResult submitFlow() { FlowResult flowResult = this.submitCurrentFlow(); - if (this.isSkipIfSameApprover() && !flowResult.isOver()) { + if (this.isSkipIfSameApprover() && !flowResult.isOver() && !flowResult.isStart()) { List flowRecords = flowResult.matchRecordByOperator(currentOperator); FlowResult result = flowResult; if (!flowRecords.isEmpty()) { diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java index b2f90c6e..63502c97 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java @@ -713,6 +713,89 @@ void postponedAndUrgeTest() { } + /** + * 一直退回的测试 + */ + @Test + void rejectAllTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .skipIfSameApprover(true) + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(user.getUserId())) + .node("办公室领导审批", "office", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("办公室领导审批", "dept", "office") + .relation("总经理审批", "office", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + + // 查看流程详情 + FlowDetail flowDetail = flowService.detail(userTodo.getId()); + assertEquals("我要出去看看", ((Leave) flowDetail.getBindData()).getTitle()); + assertTrue(flowDetail.getFlowRecord().isUnRead()); + + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.reject("不同意")); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.reject("不同意")); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + + System.out.println(userTodo.getNodeCode()); + + assertEquals("start", userTodo.getNodeCode()); + } + + /** * 部门拒绝再提交测试 */ diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 303fa950..df5397b9 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.34 + 2.9.35 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index c7913341..0497de7b 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.34 + 2.9.35 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 5efb14a2..ff0f7478 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.34 +CodingApi SpringBoot-Starter 2.9.35 springboot version (${spring-boot.version}) ------------------------------------------------------ From 78dc0fdb61545ffd642f4e46a75724fa9f000fcb Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 19 May 2025 12:00:46 +0800 Subject: [PATCH 095/129] fix #108 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../flow/service/FlowNodeService.java | 3 + .../springboot/flow/test/FlowTest3.java | 143 ++++++++++++++++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 9 files changed, 153 insertions(+), 7 deletions(-) create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest3.java diff --git a/pom.xml b/pom.xml index 62a61994..bb297715 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.35 + 2.9.36 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 394bb0d2..d5a67efd 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.35 + 2.9.36 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 5410f3df..54a02237 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.35 + 2.9.36 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 1ad05ddf..d4494e48 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.35 + 2.9.36 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java index ba755514..c0acc00a 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java @@ -121,6 +121,9 @@ public void loadDefaultBackNode(FlowRecord currentRecord) { boolean startRemove = false; for(FlowRecord historyRecord: historyRecords){ if(startRemove){ + if(historyRecord.getNodeCode().equals(currentRecord.getNodeCode())){ + continue; + } this.nextNode = flowWork.getNodeByCode(historyRecord.getNodeCode()); this.nextOperator = historyRecord.getCurrentOperator(); this.backOperator = historyRecord.getCurrentOperator(); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest3.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest3.java new file mode 100644 index 00000000..427eef19 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest3.java @@ -0,0 +1,143 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class FlowTest3 { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository, userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository, flowProcessRepository, flowBackupRepository); + + + /** + * 一直退回的测试 + */ + @Test + void rejectAllTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .skipIfSameApprover(true) + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门负责人审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(user.getUserId(), boss.getUserId())) + .node("分管领导审批", "office", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门负责人审批", "start", "dept") + .relation("分管领导审批", "dept", "office") + .relation("总经理审批", "office", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.reject("不同意")); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.reject("不同意")); + + List records = flowRecordRepository.findAll(pageRequest).getContent(); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + + System.out.println(userTodo.getNodeCode()); + + assertEquals("start", userTodo.getNodeCode()); + + // 提交流程 + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.reject("不同意")); + + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.reject("不同意")); + + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + + System.out.println(userTodo.getNodeCode()); + + assertEquals("start", userTodo.getNodeCode()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(11, records.size()); + + + } +} diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index df5397b9..4013b4de 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.35 + 2.9.36 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 0497de7b..2a1649d7 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.35 + 2.9.36 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index ff0f7478..bcd02680 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.35 +CodingApi SpringBoot-Starter 2.9.36 springboot version (${spring-boot.version}) ------------------------------------------------------ From a11dcebdae24dc0ea6b2c7e0a0f74bd3663e18d6 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 28 May 2025 19:53:27 +0800 Subject: [PATCH 096/129] merge flow record --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../flow/build/FlowWorkBuilder.java | 34 +++++++++++-------- .../springboot/flow/build/SchemaReader.java | 3 +- .../springboot/flow/domain/FlowNode.java | 12 +++++++ .../springboot/flow/pojo/FlowDetail.java | 9 +++++ .../springboot/flow/record/FlowMerge.java | 14 ++++++++ .../springboot/flow/record/FlowRecord.java | 7 ++++ .../flow/repository/FlowRecordRepository.java | 9 +++++ .../serializable/FlowNodeSerializable.java | 7 +++- .../flow/service/impl/FlowDetailService.java | 13 ++++++- .../repository/FlowRecordRepositoryImpl.java | 11 ++++++ .../springboot/flow/test/ErrorTest.java | 4 +-- .../springboot/flow/test/FlowTest.java | 2 +- .../springboot/flow/test/ScriptBuildTest.java | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 20 files changed, 112 insertions(+), 29 deletions(-) create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowMerge.java diff --git a/pom.xml b/pom.xml index bb297715..68ce4625 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.9.36 + 2.10.0 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index d5a67efd..46d175a3 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.36 + 2.10.0 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 54a02237..a8da394d 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.9.36 + 2.10.0 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index d4494e48..03fb08d1 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.36 + 2.10.0 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java index b9908f14..e8a07925 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java @@ -73,43 +73,47 @@ public FlowWork build() { public class Nodes { - public Nodes node(String id, String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, TitleGenerator titleGenerator, ErrTrigger errTrigger, boolean editable, List buttons) { - FlowNode node = new FlowNode(id, name, code, view, NodeType.parser(code), approvalType, titleGenerator, operatorMatcher, timeout, errTrigger, editable, buttons); + public Nodes node(String id, String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, TitleGenerator titleGenerator, ErrTrigger errTrigger, boolean editable, boolean mergeable, List buttons) { + FlowNode node = new FlowNode(id, name, code, view, NodeType.parser(code), approvalType, titleGenerator, operatorMatcher, timeout, errTrigger, editable,mergeable, buttons); work.addNode(node); return this; } public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, boolean editable) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable, null); + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable,false, null); } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, boolean editable, List buttons) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable, buttons); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, boolean editable,boolean mergeable) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable,mergeable, null); + } + + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, boolean editable,boolean mergeable, List buttons) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable,mergeable, buttons); } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, boolean editable) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable, null); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, boolean editable,boolean mergeable) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable,mergeable, null); } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, boolean editable, List buttons) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable, buttons); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, boolean editable,boolean mergeable, List buttons) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable,mergeable, buttons); } public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, List buttons) { - return node(name, code, view, approvalType, operatorMatcher, true, buttons); + return node(name, code, view, approvalType, operatorMatcher, true,false, buttons); } public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher) { - return node(name, code, view, approvalType, operatorMatcher, true, null); + return node(name, code, view, approvalType, operatorMatcher, true,false, null); } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable, List buttons) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable, buttons); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable,boolean mergeable, List buttons) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable,mergeable, buttons); } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable, null); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable,boolean mergeable) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable,mergeable, null); } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java index f169b75e..09217db6 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java @@ -48,6 +48,7 @@ private void loadNodes() { String titleGenerator = properties.getString("titleGenerator"); String name = properties.getString("name"); boolean editable = properties.getBoolean("editable"); + boolean mergeable = properties.getBoolean("mergeable"); String view = properties.getString("view"); String type = properties.getString("type"); String approvalType = properties.getString("approvalType"); @@ -59,7 +60,7 @@ private void loadNodes() { buttons = properties.getJSONArray("buttons").toJavaList(FlowButton.class); } FlowNode flowNode = new FlowNode(id, name, code, view, NodeType.parser(type), ApprovalType.parser(approvalType), new TitleGenerator(titleGenerator), - new OperatorMatcher(operatorMatcher), timeout, StringUtils.hasLength(errTrigger) ? new ErrTrigger(errTrigger) : null, editable, buttons); + new OperatorMatcher(operatorMatcher), timeout, StringUtils.hasLength(errTrigger) ? new ErrTrigger(errTrigger) : null, editable,mergeable, buttons); flowNodes.add(flowNode); } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java index 1e9985fb..fcad0edd 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java @@ -78,6 +78,14 @@ public class FlowNode { */ private boolean editable; + /** + * 是否合并记录 + *

+ * 如果为true,则表示该节点可以合并记录 + */ + private boolean mergeable; + + /** * 创建时间 */ @@ -148,6 +156,7 @@ public FlowNodeSerializable toSerializable() { this.approvalType, this.operatorMatcher.getScript(), this.editable, + this.mergeable, this.createTime, this.updateTime, this.timeout, @@ -168,6 +177,7 @@ public FlowNode(String id, long timeout, ErrTrigger errTrigger, boolean editable, + boolean mergeable, List buttons) { this.id = id; this.code = code; @@ -182,6 +192,7 @@ public FlowNode(String id, this.errTrigger = errTrigger; this.timeout = timeout; this.editable = editable; + this.mergeable = mergeable; this.buttons = buttons; } @@ -229,6 +240,7 @@ public FlowRecord createRecord(long workId, FlowRecord record = new FlowRecord(); record.setProcessId(processId); record.setNodeCode(this.code); + record.setMergeable(this.mergeable); record.setCreateTime(System.currentTimeMillis()); record.setWorkId(workId); record.setWorkCode(workCode); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java index 1b73841f..5dc44e71 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java @@ -5,6 +5,7 @@ import com.codingapi.springboot.flow.domain.FlowNode; import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.record.FlowMerge; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.user.IFlowOperator; import lombok.Getter; @@ -64,8 +65,14 @@ public class FlowDetail { */ private final boolean canHandle; + /** + * 合并记录 + */ + private final List mergeRecords; + public FlowDetail(FlowRecord flowRecord, + List mergeRecords, BindDataSnapshot snapshot, FlowWork flowWork, List historyRecords, @@ -73,6 +80,7 @@ public FlowDetail(FlowRecord flowRecord, boolean canHandle) { this.operators = operators; this.flowRecord = flowRecord; + this.mergeRecords = mergeRecords; this.flowWork = flowWork; this.bindData = snapshot.toBindData(); this.historyRecords = historyRecords; @@ -92,6 +100,7 @@ public FlowDetail(FlowWork flowWork, this.operators = operators; this.flowCreateTime = 0; this.flowRecord = null; + this.mergeRecords = null; this.historyRecords = null; this.bindData = null; this.opinions = null; diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowMerge.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowMerge.java new file mode 100644 index 00000000..5ef07031 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowMerge.java @@ -0,0 +1,14 @@ +package com.codingapi.springboot.flow.record; + +import com.codingapi.springboot.flow.bind.IBindData; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class FlowMerge { + + private final FlowRecord flowRecord; + private final IBindData bindData; + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java index fbd303e8..ecd28cb9 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -49,6 +49,12 @@ public class FlowRecord { */ private String nodeCode; + + /** + * 是否可合并 + */ + private boolean mergeable; + /** * 流程标题 */ @@ -402,6 +408,7 @@ public FlowRecord copy() { record.setWorkCode(this.workCode); record.setProcessId(this.processId); record.setNodeCode(this.nodeCode); + record.setMergeable(this.mergeable); record.setTitle(this.title); record.setCurrentOperator(this.currentOperator); record.setFlowType(this.flowType); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java index 292d40e5..8987ec6c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java @@ -48,6 +48,15 @@ public interface FlowRecordRepository { */ List findFlowRecordByProcessId(String processId); + /** + * 获取合并的流程记录 + * @param workCode 流程编码 + * @param nodeCode 节点编码 + * @param currentOperatorId 当前操作者ID + * @return List of FlowRecord + */ + List findMergeFlowRecordById(String workCode,String nodeCode,long currentOperatorId); + /** * 查询所有未完成的流程记录 diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java index d6e80dea..b517104c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java @@ -69,6 +69,11 @@ public class FlowNodeSerializable implements Serializable { */ private boolean editable; + /** + * 是否可合并审批 + */ + private boolean mergeable; + /** * 创建时间 */ @@ -95,6 +100,6 @@ public class FlowNodeSerializable implements Serializable { public FlowNode toFlowNode() { return new FlowNode(id, code, name, new TitleGenerator(titleGenerator), type, view, approvalType, - new OperatorMatcher(operatorMatcher), editable, createTime, updateTime, timeout, errTrigger == null ? null : new ErrTrigger(errTrigger),buttons); + new OperatorMatcher(operatorMatcher), editable, mergeable, createTime, updateTime, timeout, errTrigger == null ? null : new ErrTrigger(errTrigger), buttons); } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java index e684f422..718784d8 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java @@ -5,6 +5,7 @@ import com.codingapi.springboot.flow.domain.FlowNode; import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.record.FlowMerge; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.*; import com.codingapi.springboot.flow.service.FlowRecordVerifyService; @@ -46,6 +47,16 @@ public FlowDetail detail(long recordId, IFlowOperator currentOperator) { FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + List mergeRecords = null; + if(flowRecord.isTodo() && flowRecord.isMergeable()){ + List flowRecords = flowRecordRepository.findMergeFlowRecordById(flowRecord.getWorkCode(),flowRecord.getNodeCode(),currentOperator.getUserId()); + if(!flowRecords.isEmpty()){ + mergeRecords = flowRecords.stream().map(record->{ + BindDataSnapshot bindDataSnapshot = flowBindDataRepository.getBindDataSnapshotById(record.getSnapshotId()); + return new FlowMerge(record,bindDataSnapshot.toBindData()); + }).collect(Collectors.toList()); + } + } BindDataSnapshot snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); List flowRecords = @@ -64,7 +75,7 @@ public FlowDetail detail(long recordId, IFlowOperator currentOperator) { } } - return new FlowDetail(flowRecord, snapshot, flowWork, flowRecords, operators, currentOperator != null && flowRecord.isTodo() && flowRecord.isOperator(currentOperator)); + return new FlowDetail(flowRecord,mergeRecords, snapshot, flowWork, flowRecords, operators, currentOperator != null && flowRecord.isTodo() && flowRecord.isOperator(currentOperator)); } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java index 59f60d7b..603d5e42 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java @@ -43,6 +43,17 @@ public List findFlowRecordByPreId(long preId) { return cache.stream().filter(record -> record.getPreId() == preId).collect(Collectors.toList()); } + @Override + public List findMergeFlowRecordById(String workCode, String nodeCode, long operatorId) { + return cache.stream() + .filter(record -> record.isTodo() && record.getCurrentOperator().getUserId() == operatorId + && record.getWorkCode().equals(workCode) + && record.getNodeCode().equals(nodeCode) + && record.isMergeable() + ) + .collect(Collectors.toList()); + } + @Override public List findFlowRecordByProcessId(String processId) { return cache.stream().filter(record -> record.getProcessId().equals(processId)) diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java index 97010832..d04a3124 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java @@ -53,7 +53,7 @@ void errorMatcherOperatorTest(){ .title("请假流程") .nodes() .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) - .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createOperatorErrTrigger("+dept.getId()+")}"), true) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createOperatorErrTrigger("+dept.getId()+")}"), true,false) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() @@ -145,7 +145,7 @@ void errorMatcherNodeTest(){ .title("请假流程") .nodes() .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) - .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createNodeErrTrigger('manager')}"), true) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createNodeErrTrigger('manager')}"), true,false) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java index 63502c97..bf6024b9 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java @@ -388,7 +388,7 @@ void saveDisableTest() { .title("请假流程") .nodes() .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) - .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId()), false) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId()), false,false) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java index e41a359a..a319393a 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java @@ -15,7 +15,7 @@ public class ScriptBuildTest { @Test void copy() { User user = new User("张三"); - String script = "{\"nodes\":[{\"id\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"type\":\"start-node\",\"x\":593,\"y\":96,\"properties\":{\"name\":\"开始节点\",\"code\":\"start\",\"type\":\"START\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"type\":\"node-node\",\"x\":620,\"y\":239,\"properties\":{\"name\":\"流程节点\",\"code\":\"flow\",\"type\":\"APPROVAL\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '8899-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"SIGN\",\"timeout\":10,\"id\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"custom\",\"errTriggerType\":\"custom\"}},{\"id\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"type\":\"over-node\",\"x\":828,\"y\":582,\"properties\":{\"name\":\"结束节点\",\"code\":\"over\",\"type\":\"OVER\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"type\":\"circulate-node\",\"x\":839,\"y\":409,\"properties\":{\"name\":\"抄送节点\",\"code\":\"circulate\",\"type\":\"CIRCULATE\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCreateOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"CIRCULATE\",\"timeout\":0,\"id\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"width\":200,\"height\":45}}],\"edges\":[{\"id\":\"b68837fb-dca8-41d2-908c-dc079a7f61de\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"targetNodeId\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"startPoint\":{\"x\":593,\"y\":118.5},\"endPoint\":{\"x\":620,\"y\":216.5},\"pointsList\":[{\"x\":593,\"y\":118.5},{\"x\":593,\"y\":218.5},{\"x\":620,\"y\":116.5},{\"x\":620,\"y\":216.5}]},{\"id\":\"73e04b95-50f6-44cc-a960-d3007d27fd48\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":2,\"back\":false},\"sourceNodeId\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"targetNodeId\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"startPoint\":{\"x\":720,\"y\":239},\"endPoint\":{\"x\":739,\"y\":409},\"pointsList\":[{\"x\":720,\"y\":239},{\"x\":820,\"y\":239},{\"x\":639,\"y\":409},{\"x\":739,\"y\":409}]},{\"id\":\"f6929c79-b168-4c3c-9f8f-9dc21fcaf29d\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"targetNodeId\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"startPoint\":{\"x\":839,\"y\":431.5},\"endPoint\":{\"x\":828,\"y\":559.5},\"pointsList\":[{\"x\":839,\"y\":431.5},{\"x\":839,\"y\":531.5},{\"x\":828,\"y\":459.5},{\"x\":828,\"y\":559.5}]}]}"; + String script = "{\"nodes\":[{\"id\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"type\":\"start-node\",\"x\":593,\"y\":96,\"properties\":{\"name\":\"开始节点\",\"code\":\"start\",\"type\":\"START\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"mergeable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"type\":\"node-node\",\"x\":620,\"y\":239,\"properties\":{\"name\":\"流程节点\",\"code\":\"flow\",\"type\":\"APPROVAL\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"mergeable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '8899-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"SIGN\",\"timeout\":10,\"id\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"custom\",\"errTriggerType\":\"custom\"}},{\"id\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"type\":\"over-node\",\"x\":828,\"y\":582,\"properties\":{\"name\":\"结束节点\",\"code\":\"over\",\"type\":\"OVER\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"mergeable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"type\":\"circulate-node\",\"x\":839,\"y\":409,\"properties\":{\"name\":\"抄送节点\",\"code\":\"circulate\",\"type\":\"CIRCULATE\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCreateOperator().getUserId()];}\",\"editable\":true,\"mergeable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"CIRCULATE\",\"timeout\":0,\"id\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"width\":200,\"height\":45}}],\"edges\":[{\"id\":\"b68837fb-dca8-41d2-908c-dc079a7f61de\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"targetNodeId\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"startPoint\":{\"x\":593,\"y\":118.5},\"endPoint\":{\"x\":620,\"y\":216.5},\"pointsList\":[{\"x\":593,\"y\":118.5},{\"x\":593,\"y\":218.5},{\"x\":620,\"y\":116.5},{\"x\":620,\"y\":216.5}]},{\"id\":\"73e04b95-50f6-44cc-a960-d3007d27fd48\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":2,\"back\":false},\"sourceNodeId\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"targetNodeId\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"startPoint\":{\"x\":720,\"y\":239},\"endPoint\":{\"x\":739,\"y\":409},\"pointsList\":[{\"x\":720,\"y\":239},{\"x\":820,\"y\":239},{\"x\":639,\"y\":409},{\"x\":739,\"y\":409}]},{\"id\":\"f6929c79-b168-4c3c-9f8f-9dc21fcaf29d\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"targetNodeId\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"startPoint\":{\"x\":839,\"y\":431.5},\"endPoint\":{\"x\":828,\"y\":559.5},\"pointsList\":[{\"x\":839,\"y\":431.5},{\"x\":839,\"y\":531.5},{\"x\":828,\"y\":459.5},{\"x\":828,\"y\":559.5}]}]}"; FlowWork flowWork = FlowWorkBuilder.builder(user) .title("请假流程") .schema(script) diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 4013b4de..053b4815 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.9.36 + 2.10.0 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 2a1649d7..d4273854 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.9.36 + 2.10.0 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index bcd02680..45a7845b 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.9.36 +CodingApi SpringBoot-Starter 2.10.0 springboot version (${spring-boot.version}) ------------------------------------------------------ From ae885ee5a1b355067f56e315479e9857d443ef3a Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 28 May 2025 20:34:12 +0800 Subject: [PATCH 097/129] fix sql build --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../java/com/codingapi/springboot/fast/jpa/SQLBuilder.java | 4 ++++ springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- springboot-starter/src/main/resources/META-INF/banner.txt | 2 +- 8 files changed, 11 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 68ce4625..44c7bc45 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.0 + 2.10.1 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 46d175a3..a8d45635 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.0 + 2.10.1 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index a8da394d..12aa37bf 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.0 + 2.10.1 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java index 020e2802..8f6bec96 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java @@ -23,6 +23,10 @@ public SQLBuilder(Class clazz, String sql) { this(clazz, sql, "select count(1) from " + sql); } + public SQLBuilder(String sql,String countSql) { + this(null, sql, countSql); + } + public SQLBuilder(Class clazz, String sql, String countSQL) { this.countSQLBuilder = new StringBuilder(countSQL); this.sqlBuilder = new StringBuilder(sql); diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 03fb08d1..7db238a6 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.0 + 2.10.1 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 053b4815..aa859a81 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.0 + 2.10.1 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index d4273854..cb4d311e 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.0 + 2.10.1 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 45a7845b..98ad746a 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.0 +CodingApi SpringBoot-Starter 2.10.1 springboot version (${spring-boot.version}) ------------------------------------------------------ From d141d18a0d679c8057908dada9e0c4a82c8d9601 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Tue, 10 Jun 2025 10:41:53 +0800 Subject: [PATCH 098/129] add flow map data & save event state --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/bind/FlowMapBindData.java | 48 +++++++ .../springboot/flow/bind/IBindData.java | 20 +++ .../flow/event/FlowApprovalEvent.java | 25 +++- .../flow/service/impl/FlowSaveService.java | 12 ++ .../flow/service/impl/FlowStartService.java | 1 + .../codingapi/springboot/flow/flow/Leave.java | 4 + .../springboot/flow/flow/Leave2.java | 23 ++++ .../flow/repository/LeaveRepository.java | 5 + .../springboot/flow/test/FlowMapTest.java | 127 ++++++++++++++++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 16 files changed, 270 insertions(+), 9 deletions(-) create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/FlowMapBindData.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave2.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowMapTest.java diff --git a/pom.xml b/pom.xml index 44c7bc45..809919f1 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.1 + 2.10.2 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index a8d45635..024f93f3 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.1 + 2.10.2 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 12aa37bf..fcfa7b86 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.1 + 2.10.2 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 7db238a6..68d1b1f0 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.1 + 2.10.2 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/FlowMapBindData.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/FlowMapBindData.java new file mode 100644 index 00000000..2648956d --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/FlowMapBindData.java @@ -0,0 +1,48 @@ +package com.codingapi.springboot.flow.bind; + +import com.alibaba.fastjson.JSONObject; + +import java.util.HashMap; + +/** + * 流程绑定Map数据对象,用于分布式服务下的流程对象数据传递能力 + * 该对象中,将clazzName 当做了普通的key来使用, + */ +public class FlowMapBindData extends HashMap implements IBindData { + + + /** + * 获取类名称 + * + * @return 类名称 + */ + @Override + public String getClazzName() { + return (String) this.get(CLASS_NAME_KEY); + } + + /** + * 转化为类对象 + */ + @Override + public T toJavaObject(Class clazz) { + return JSONObject.parseObject(toJsonSnapshot(), clazz); + } + + public static FlowMapBindData fromJson(String json) { + return JSONObject.parseObject(json, FlowMapBindData.class); + } + + public static FlowMapBindData fromObject(Object obj) { + return JSONObject.parseObject(JSONObject.toJSONString(obj), FlowMapBindData.class); + } + + public static FlowMapBindData fromJson(JSONObject json) { + return JSONObject.parseObject(json.toJSONString(), FlowMapBindData.class); + } + + public boolean match(String matchKey) { + String className = this.getClazzName(); + return matchKey.equals(className); + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java index 4814cdcb..5c152799 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java @@ -7,6 +7,8 @@ */ public interface IBindData { + String CLASS_NAME_KEY = "clazzName"; + /** * 数据快照 * @@ -19,9 +21,27 @@ default String toJsonSnapshot() { /** * 获取类名称 + * * @return 类名称 */ default String getClazzName() { return this.getClass().getName(); } + + + /** + * 类对象匹配 + */ + default boolean match(String dataKey) { + String className = this.getClazzName(); + return dataKey.equals(className); + } + + + /** + * 转化为类对象 + */ + default T toJavaObject(Class clazz) { + return (T) this; + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java index ba6665ad..d6b8f406 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java @@ -34,6 +34,8 @@ public class FlowApprovalEvent implements ISyncEvent { public static final int STATE_URGE = 8; // 抄送 public static final int STATE_CIRCULATE = 9; + // 保存 + public static final int STATE_SAVE = 10; private final int state; @@ -52,8 +54,23 @@ public FlowApprovalEvent(int state, FlowRecord flowRecord, IFlowOperator operato } - public boolean match(Class bindDataClass) { - return bindDataClass.isInstance(bindData); + public boolean match(String matchKey) { + return bindData.match(matchKey); + } + + /** + * 匹配类名 + * 当前bingData下的clazzName变成了普通的key字段了,推荐使用match(String matchKey)方法 + * @param clazz 类名 + * @return 是否匹配 + */ + @Deprecated + public boolean match(Class clazz) { + return bindData.match(clazz.getName()); + } + + public T toJavaObject(Class clazz) { + return bindData.toJavaObject(clazz); } public boolean isUrge() { @@ -64,6 +81,10 @@ public boolean isTodo() { return state == STATE_TODO; } + public boolean isSave() { + return state == STATE_SAVE; + } + public boolean isCreate() { return state == STATE_CREATE; } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java index 6e57d924..f73c6550 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java @@ -2,7 +2,9 @@ import com.codingapi.springboot.flow.bind.BindDataSnapshot; import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.FlowBindDataRepository; import com.codingapi.springboot.flow.repository.FlowProcessRepository; @@ -10,6 +12,7 @@ import com.codingapi.springboot.flow.repository.FlowWorkRepository; import com.codingapi.springboot.flow.service.FlowRecordVerifyService; import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; import lombok.AllArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -48,6 +51,15 @@ public void save(long recordId, IFlowOperator currentOperator, IBindData bindDat flowRecord.setOpinion(opinion); flowRecordRepository.update(flowRecord); + + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_SAVE, + flowRecord, + flowRecord.getCurrentOperator(), + flowWork, + snapshot.toBindData()), + true); } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java index da90bf88..d035a5e4 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java @@ -189,6 +189,7 @@ public FlowResult startFlow() { for (FlowRecord record : records) { this.pushEvent(FlowApprovalEvent.STATE_CREATE, record); this.pushEvent(FlowApprovalEvent.STATE_TODO, record); + this.pushEvent(FlowApprovalEvent.STATE_SAVE, record); } // 当前的审批记录 return new FlowResult(flowWork, records); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave.java index 2d02fed0..c7b3a7ca 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave.java @@ -1,11 +1,15 @@ package com.codingapi.springboot.flow.flow; import com.codingapi.springboot.flow.bind.IBindData; +import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; @Setter @Getter +@AllArgsConstructor +@NoArgsConstructor public class Leave implements IBindData { private long id; diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave2.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave2.java new file mode 100644 index 00000000..c6612bc4 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave2.java @@ -0,0 +1,23 @@ +package com.codingapi.springboot.flow.flow; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class Leave2 { + + private long id; + private String title; + private int days; + + public Leave2(String title) { + this(title,0); + } + + public Leave2(String title, int days) { + this.title = title; + this.days = days; + } + +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/LeaveRepository.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/LeaveRepository.java index dd4f50f1..1342286b 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/LeaveRepository.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/LeaveRepository.java @@ -1,6 +1,7 @@ package com.codingapi.springboot.flow.repository; import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.flow.Leave2; import java.util.ArrayList; import java.util.List; @@ -15,4 +16,8 @@ public void save(Leave leave) { leave.setId(cache.size()); } } + public void save(Leave2 leave2) { + Leave leave = new Leave(leave2.getId(), leave2.getTitle(), leave2.getDays()); + this.save(leave); + } } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowMapTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowMapTest.java new file mode 100644 index 00000000..a14c7e98 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowMapTest.java @@ -0,0 +1,127 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.FlowMapBindData; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave2; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class FlowMapTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository, userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository, flowProcessRepository, flowBackupRepository); + + /** + * map数据绑定对象测试 + */ + @Test + void mapFlowTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave2 leave = new Leave2("我要出去看看"); + FlowMapBindData bindData = FlowMapBindData.fromObject(leave); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, bindData, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + // 保存流程 + leave.setTitle("我要出去看看~~"); + bindData = FlowMapBindData.fromObject(leave); + flowService.save(userTodo.getId(), user, bindData, "暂存"); + + // 查看流程详情 + FlowDetail flowDetail = flowService.detail(userTodo.getId(), user); + assertEquals("我要出去看看~~", (flowDetail.getBindData().toJavaObject(Leave2.class)).getTitle()); + assertTrue(flowDetail.getFlowRecord().isRead()); + + + flowService.submitFlow(userTodo.getId(), user, bindData, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, bindData, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, bindData, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + + } +} diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index aa859a81..91e08ba7 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.1 + 2.10.2 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index cb4d311e..bb46512e 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.1 + 2.10.2 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 98ad746a..845aa16c 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.1 +CodingApi SpringBoot-Starter 2.10.2 springboot version (${spring-boot.version}) ------------------------------------------------------ From 11d821918f665fe876cb3352435fd875a9db8f8b Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 13 Jun 2025 11:22:25 +0800 Subject: [PATCH 099/129] fix 2.10.3 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../com/codingapi/springboot/flow/service/FlowNodeService.java | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- springboot-starter/src/main/resources/META-INF/banner.txt | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 809919f1..daad4555 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.2 + 2.10.3 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 024f93f3..c4a5dbc7 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.2 + 2.10.3 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index fcfa7b86..94a3ff78 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.2 + 2.10.3 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 68d1b1f0..b366126e 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.2 + 2.10.3 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java index c0acc00a..bcc58942 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java @@ -164,7 +164,7 @@ public void loadCustomBackNode(FlowNode flowNode, long parentRecordId) { } this.nextNode = nextNode; this.nextOperator = flowOperator; - this.backOperator = flowOperator; + this.backOperator = null; } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 91e08ba7..1482367f 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.2 + 2.10.3 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index bb46512e..d083955a 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.2 + 2.10.3 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 845aa16c..7b4110d8 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.2 +CodingApi SpringBoot-Starter 2.10.3 springboot version (${spring-boot.version}) ------------------------------------------------------ From 4eccebafb3a495f58abf2e81b27ecfeafb4da877 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 20 Jun 2025 21:37:54 +0800 Subject: [PATCH 100/129] 2.10.4 add HttpSecurityCustomer --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- .../security/AutoConfiguration.java | 26 ++++++---- .../customer/DefaultHttpSecurityCustomer.java | 50 +++++++++++++++++++ .../customer/HttpSecurityCustomer.java | 9 ++++ .../CodingApiSecurityProperties.java | 9 ++++ springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 11 files changed, 91 insertions(+), 17 deletions(-) create mode 100644 springboot-starter-security/src/main/java/com/codingapi/springboot/security/customer/DefaultHttpSecurityCustomer.java create mode 100644 springboot-starter-security/src/main/java/com/codingapi/springboot/security/customer/HttpSecurityCustomer.java diff --git a/pom.xml b/pom.xml index daad4555..d2d5d0dc 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.3 + 2.10.4 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index c4a5dbc7..4b6698a5 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.3 + 2.10.4 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 94a3ff78..e1a9af60 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.3 + 2.10.4 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index b366126e..e27424b1 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.3 + 2.10.4 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 1482367f..7abb2fee 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.3 + 2.10.4 springboot-starter-security diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java index b60f597c..b8b21a76 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java @@ -2,6 +2,8 @@ import com.codingapi.springboot.security.configurer.HttpSecurityConfigurer; import com.codingapi.springboot.security.controller.VersionController; +import com.codingapi.springboot.security.customer.DefaultHttpSecurityCustomer; +import com.codingapi.springboot.security.customer.HttpSecurityCustomer; import com.codingapi.springboot.security.dto.request.LoginRequest; import com.codingapi.springboot.security.dto.response.LoginResponse; import com.codingapi.springboot.security.filter.*; @@ -67,6 +69,11 @@ public AuthenticationTokenFilter authenticationTokenFilter() { }; } + @Bean + @ConditionalOnMissingBean + public HttpSecurityCustomer httpSecurityCustomer(CodingApiSecurityProperties properties){ + return new DefaultHttpSecurityCustomer(properties); + } @Bean @ConditionalOnMissingBean @@ -91,16 +98,15 @@ public LoginResponse postHandle(HttpServletRequest request, HttpServletResponse @Bean @ConditionalOnMissingBean - public SecurityFilterChain filterChain(HttpSecurity security, TokenGateway tokenGateway, SecurityLoginHandler loginHandler, - CodingApiSecurityProperties properties, AuthenticationTokenFilter authenticationTokenFilter) throws Exception { - //disable basic auth - security.httpBasic().disable(); - - //before add addCorsMappings to enable cors. - security.cors(); - if (properties.isDisableCsrf()) { - security.csrf().disable(); - } + public SecurityFilterChain filterChain(HttpSecurity security, + HttpSecurityCustomer httpSecurityCustomer, + TokenGateway tokenGateway, + SecurityLoginHandler loginHandler, + CodingApiSecurityProperties properties, + AuthenticationTokenFilter authenticationTokenFilter) throws Exception { + + httpSecurityCustomer.customize(security); + security.apply(new HttpSecurityConfigurer(tokenGateway, loginHandler, properties, authenticationTokenFilter)); security .exceptionHandling() diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/customer/DefaultHttpSecurityCustomer.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/customer/DefaultHttpSecurityCustomer.java new file mode 100644 index 00000000..02733c6f --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/customer/DefaultHttpSecurityCustomer.java @@ -0,0 +1,50 @@ +package com.codingapi.springboot.security.customer; + +import com.codingapi.springboot.security.properties.CodingApiSecurityProperties; +import lombok.AllArgsConstructor; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; + +@AllArgsConstructor +public class DefaultHttpSecurityCustomer implements HttpSecurityCustomer { + + private final CodingApiSecurityProperties properties; + + @Override + public void customize(HttpSecurity security) throws Exception { + //disable basic auth + if (properties.isDisableBasicAuth()) { + security.httpBasic(AbstractHttpConfigurer::disable); + } + + //disable frame options + if (properties.isDisableFrameOptions()) { + security.headers(new Customizer>() { + @Override + public void customize(HeadersConfigurer httpSecurityHeadersConfigurer) { + httpSecurityHeadersConfigurer.frameOptions(new Customizer.FrameOptionsConfig>() { + @Override + public void customize(HeadersConfigurer.FrameOptionsConfig frameOptionsConfig) { + frameOptionsConfig.disable(); + } + }); + } + }); + } + + //before add addCorsMappings to enable cors. + security.cors(httpSecurityCorsConfigurer -> { + if (properties.isDisableCors()) { + httpSecurityCorsConfigurer.disable(); + } + }); + + security.csrf(httpSecurityCsrfConfigurer -> { + if (properties.isDisableCsrf()) { + httpSecurityCsrfConfigurer.disable(); + } + }); + } +} diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/customer/HttpSecurityCustomer.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/customer/HttpSecurityCustomer.java new file mode 100644 index 00000000..ddc35dd6 --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/customer/HttpSecurityCustomer.java @@ -0,0 +1,9 @@ +package com.codingapi.springboot.security.customer; + +import org.springframework.security.config.annotation.web.builders.HttpSecurity; + +public interface HttpSecurityCustomer { + + void customize(HttpSecurity security) throws Exception; + +} diff --git a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/properties/CodingApiSecurityProperties.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/properties/CodingApiSecurityProperties.java index 4a33d91b..0db1dad0 100644 --- a/springboot-starter-security/src/main/java/com/codingapi/springboot/security/properties/CodingApiSecurityProperties.java +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/properties/CodingApiSecurityProperties.java @@ -38,6 +38,15 @@ public class CodingApiSecurityProperties { */ private String aseIv = "QUNYRkdIQEVEUyNYQ1phcw=="; + /** + * 禁用Basic Auth + */ + private boolean disableBasicAuth = true; + + /** + * 禁用FrameOptions + */ + private boolean disableFrameOptions = true; /** * 启用禁用CSRF diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index d083955a..a7db9a65 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.3 + 2.10.4 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 7b4110d8..685e5ca1 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.3 +CodingApi SpringBoot-Starter 2.10.4 springboot version (${spring-boot.version}) ------------------------------------------------------ From 59ed4505ae9f64c7a7c130ab340f5484653b8bb2 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 27 Jun 2025 14:52:38 +0800 Subject: [PATCH 101/129] add Any --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../springboot/framework/annotation/ColumnType.java | 5 +++++ springboot-starter/src/main/resources/META-INF/banner.txt | 2 +- 8 files changed, 12 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index d2d5d0dc..999755a7 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.4 + 2.10.5 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 4b6698a5..fa3f09c0 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.4 + 2.10.5 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index e1a9af60..f7e84726 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.4 + 2.10.5 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index e27424b1..5100e5d9 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.4 + 2.10.5 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 7abb2fee..ffebe777 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.4 + 2.10.5 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index a7db9a65..a314e5c3 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.4 + 2.10.5 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/ColumnType.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/ColumnType.java index 215814c1..40bb84f1 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/ColumnType.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/ColumnType.java @@ -44,4 +44,9 @@ public enum ColumnType { * JSON */ JSON, + + /** + * 任意 + */ + Any } diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 685e5ca1..9555bc0b 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.4 +CodingApi SpringBoot-Starter 2.10.5 springboot version (${spring-boot.version}) ------------------------------------------------------ From b7474c9b17e56d107266dbc479e4ccb0d5ac9358 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 30 Jun 2025 11:54:45 +0800 Subject: [PATCH 102/129] fix #117 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/domain/FlowRelation.java | 3 + .../flow/service/FlowNodeService.java | 28 +++- .../flow/service/impl/FlowSubmitService.java | 2 +- .../springboot/flow/test/ErrorTest.java | 80 +++++++++ .../springboot/flow/test/FlowTest.java | 157 ++++++++++++++++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/event/SpringEventHandler.java | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- .../framework/event/EventPusherTest.java | 32 ++++ 14 files changed, 306 insertions(+), 12 deletions(-) create mode 100644 springboot-starter/src/test/java/com/codingapi/springboot/framework/event/EventPusherTest.java diff --git a/pom.xml b/pom.xml index 999755a7..633775d0 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.5 + 2.10.6 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index fa3f09c0..63fac898 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.5 + 2.10.6 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index f7e84726..9ba33c40 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.5 + 2.10.6 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 5100e5d9..d41a8852 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.5 + 2.10.6 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowRelation.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowRelation.java index c93dead9..16f7df4f 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowRelation.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowRelation.java @@ -17,6 +17,9 @@ @AllArgsConstructor public class FlowRelation { + + public static final int DEFAULT_ORDER = -100; + /** * 关系id */ diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java index bcc58942..96f5258c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java @@ -13,6 +13,7 @@ import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.FlowOperatorRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.trigger.OutTrigger; import com.codingapi.springboot.flow.user.IFlowOperator; import com.codingapi.springboot.framework.event.EventPusher; import lombok.Getter; @@ -115,7 +116,7 @@ public void loadDefaultBackNode(FlowRecord currentRecord) { throw new IllegalArgumentException("back node not found"); } FlowRecord record = historyRecords.get(index); - if (record.isDone()) { + if (record.isDone() && record.getId()== currentRecord.getPreId()) { // 是连续的回退节点时,则根据流程记录的状态来判断 if(record.isReject()){ boolean startRemove = false; @@ -174,7 +175,28 @@ public void loadCustomBackNode(FlowNode flowNode, long parentRecordId) { * @return 下一个节点 */ private FlowNode matcherNextNode(FlowNode flowNode, boolean back) { - List relations = flowWork.getRelations().stream() + List currentRelations = new ArrayList<>(flowWork.getRelations()); + if(back){ + String preCode = FlowNode.CODE_START; + if(flowRecord.getPreId()!=0){ + FlowRecord preRecord = flowRecordRepository.getFlowRecordById(flowRecord.getPreId()); + if(preRecord!=null){ + preCode = preRecord.getNodeCode(); + while (preCode.equals(flowRecord.getNodeCode())){ + preRecord = flowRecordRepository.getFlowRecordById(preRecord.getPreId()); + if(preRecord==null){ + break; + } + preCode = preRecord.getNodeCode(); + } + } + } + FlowRelation backRelation = new FlowRelation("defaultId", + "默认回退关系", flowNode, flowWork.getNodeByCode(preCode), OutTrigger.defaultOutTrigger(), FlowRelation.DEFAULT_ORDER, true); + currentRelations.add(backRelation); + } + + List relations = currentRelations.stream() .filter(relation -> relation.sourceMatcher(flowNode.getCode())) .filter(relation -> relation.isBack() == back) .sorted((o1, o2) -> (o2.getOrder() - o1.getOrder())) @@ -315,7 +337,7 @@ private List errMatcher(FlowNode currentNode, IFlowOperator currentO List operatorIds = ((OperatorResult) errorResult).getOperatorIds(); List operators = flowOperatorRepository.findByIds(operatorIds); for (IFlowOperator operator : operators) { - FlowSession content = new FlowSession(flowRecord, flowWork, currentNode, createOperator, operator, snapshot.toBindData(), opinion, historyRecords); + FlowSession content = new FlowSession(flowRecord, flowWork, currentNode, createOperator, nextOperator, snapshot.toBindData(), opinion, historyRecords); String recordTitle = currentNode.generateTitle(content); FlowRecord record = currentNode.createRecord(flowWork.getId(), flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot, opinion.isWaiting()); recordList.add(record); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index fd188fcd..30115350 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -282,7 +282,7 @@ private FlowResult submitCurrentFlow() { if (flowNode.isUnSign()) { for (FlowRecord record : historyRecords) { if (record.isTodo() && record.getId() != flowRecord.getId()) { - record.autoPass(currentOperator, snapshot); + record.autoPass(record.getCurrentOperator(), snapshot); FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); flowRecordRepository.update(record); } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java index d04a3124..93408534 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java @@ -209,4 +209,84 @@ void errorMatcherNodeTest(){ List snapshots = flowBindDataRepository.findAll(); assertEquals(3, snapshots.size()); } + + + /** + * 相同人审批通过,指定人员审批时遇到异常,走异常节点配置 + */ + @Test + void sameUserFlow() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .skipIfSameApprover(true) + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(user.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId()), new ErrTrigger("" + + "def run(content){" + + " return content.createOperatorErrTrigger(" + dept.getUserId() + ")" + + "}"+ + ""),true, false) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(user.getUserId())); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交委托dept部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + + } } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java index bf6024b9..de27d23c 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java @@ -13,6 +13,7 @@ import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.*; import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.trigger.OutTrigger; import com.codingapi.springboot.flow.user.IFlowOperator; import com.codingapi.springboot.flow.user.User; import org.junit.jupiter.api.Test; @@ -1106,4 +1107,160 @@ void recallTest2() { } + + /** + * 非会签审批意见测试 + */ + @Test + void noSignContentTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept1 = new User("诸葛亮"); + userRepository.save(dept1); + + User dept2 = new User("黄忠"); + userRepository.save(dept2); + + User boss = new User("刘备"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept1.getUserId(), dept2.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交到部门经理 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + List dept1Todos = flowRecordRepository.findTodoByOperatorId(dept1.getUserId(), pageRequest).getContent(); + List dept2Todos = flowRecordRepository.findTodoByOperatorId(dept2.getUserId(), pageRequest).getContent(); + assertEquals(1, dept1Todos.size()); + assertEquals(1, dept2Todos.size()); + + FlowRecord dept1Todo = dept1Todos.get(0); + flowService.submitFlow(dept1Todo.getId(), dept1, leave, Opinion.pass("同意")); + + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + FlowDetail detail = flowService.detail(bossTodos.get(0).getId()); + System.out.println(detail); + + } + + + /** + * 退回与自定义退回逻辑 + */ + @Test + void rejectDefaultTest() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("诸葛亮"); + userRepository.save(dept); + + User boss = new User("刘备"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门经理审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "boss", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("开始节点->部门经理", "start", "dept") + .relation("部门经理->总经理", "dept", "boss") + .relation("总经理退回发起人", "boss", "start", new OutTrigger( + "def run(content) { \n"+ + " def days = content.getBindData().getDays(); \n"+ + " if (days > 10) { \n" + + " return true; \n"+ + " } \n"+ + " return false; \n"+ + "}" + ),1,true) + .relation("结束节点", "boss", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.reject("不同意")); + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + } } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index ffebe777..fcc55248 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.5 + 2.10.6 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index a314e5c3..ec4d5744 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.5 + 2.10.6 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/SpringEventHandler.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/SpringEventHandler.java index 5ec7b9ba..141d3c53 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/SpringEventHandler.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/SpringEventHandler.java @@ -26,7 +26,7 @@ public SpringEventHandler(List handlers) { } @Override - public void onApplicationEvent(DomainEvent domainEvent) { + public synchronized void onApplicationEvent(DomainEvent domainEvent) { String traceId = domainEvent.getTraceId(); if (domainEvent.isSync()) { diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 9555bc0b..266fc333 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.5 +CodingApi SpringBoot-Starter 2.10.6 springboot version (${spring-boot.version}) ------------------------------------------------------ diff --git a/springboot-starter/src/test/java/com/codingapi/springboot/framework/event/EventPusherTest.java b/springboot-starter/src/test/java/com/codingapi/springboot/framework/event/EventPusherTest.java new file mode 100644 index 00000000..b77a0d36 --- /dev/null +++ b/springboot-starter/src/test/java/com/codingapi/springboot/framework/event/EventPusherTest.java @@ -0,0 +1,32 @@ +package com.codingapi.springboot.framework.event; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +@SpringBootTest +public class EventPusherTest { + + private final ExecutorService executorService = Executors.newFixedThreadPool(100); + + @Test + void test() { + for (int i = 0; i < 100_0000; i++) { + executorService.execute(() -> { + try { + EventPusher.push(new DemoChangeEvent("before", "current"), true); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + try { + Thread.sleep(10000); // 等待所有任务完成 + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } +} From ef64d791e239b1ce4455ad9fc17559d529bd7d3c Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 30 Jun 2025 18:45:53 +0800 Subject: [PATCH 103/129] fix #119 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/pojo/FlowStepResult.java | 13 ++-- .../springboot/flow/service/FlowService.java | 34 ++++++---- .../flow/service/impl/FlowStepService.java | 65 ++++++++++++++----- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 10 files changed, 87 insertions(+), 39 deletions(-) diff --git a/pom.xml b/pom.xml index 633775d0..72aaab49 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.6 + 2.10.7 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 63fac898..e5f9765d 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.6 + 2.10.7 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 9ba33c40..02221020 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.6 + 2.10.7 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index d41a8852..25670f2a 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.6 + 2.10.7 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java index 36d49c36..8f4e94db 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @Getter public class FlowStepResult { @@ -17,32 +18,34 @@ public FlowStepResult() { this.flowNodes = new ArrayList<>(); } - public void addFlowNode(FlowNode flowNode,List operators) { - this.flowNodes.add(new FlowStepNode(flowNode.getId(), flowNode.getCode(),flowNode.getName(),flowNode.getType(),operators)); + public void addFlowNode(FlowNode flowNode,boolean done,List operators) { + this.flowNodes.add(new FlowStepNode(flowNode.getId(), flowNode.getCode(),flowNode.getName(),flowNode.getType(),done,operators)); } public void print(){ + System.out.println("FlowStepResult:==========================>"); for (FlowStepNode flowNode : flowNodes) { - System.out.println("flowNode = " + flowNode.getName()); + System.out.println("flowNode = " + flowNode.getName()+",done = " + flowNode.isDone() + ",type = " + flowNode.getType()+" operators = " + flowNode.getOperators().stream().map(IFlowOperator::getUserId).collect(Collectors.toList())); } } - @Getter public static class FlowStepNode{ private final String id; private final String code; private final String name; private final NodeType type; + private final boolean done; private final List operators; - public FlowStepNode(String id, String code, String name, NodeType type,List operators) { + public FlowStepNode(String id, String code, String name, NodeType type,boolean done,List operators) { this.id = id; this.code = code; this.name = name; this.type = type; this.operators = operators; + this.done = done; } } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index 0aaa054c..3990d679 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -40,13 +40,13 @@ public FlowService(FlowWorkRepository flowWorkRepository, FlowBackupRepository flowBackupRepository) { this.flowServiceRepositoryHolder = new FlowServiceRepositoryHolder(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository, flowBackupRepository); this.flowDetailService = new FlowDetailService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository); - this.flowCustomEventService = new FlowCustomEventService(flowWorkRepository,flowRecordRepository, flowProcessRepository); - this.flowRecallService = new FlowRecallService(flowWorkRepository,flowRecordRepository, flowProcessRepository); - this.flowRemoveService = new FlowRemoveService(flowWorkRepository,flowRecordRepository, flowProcessRepository); - this.flowSaveService = new FlowSaveService(flowWorkRepository,flowRecordRepository, flowBindDataRepository, flowProcessRepository); - this.flowTransferService = new FlowTransferService(flowWorkRepository,flowRecordRepository, flowBindDataRepository, flowProcessRepository); - this.flowPostponedService = new FlowPostponedService(flowWorkRepository,flowRecordRepository, flowProcessRepository); - this.flowUrgeService = new FlowUrgeService(flowWorkRepository,flowRecordRepository, flowProcessRepository); + this.flowCustomEventService = new FlowCustomEventService(flowWorkRepository, flowRecordRepository, flowProcessRepository); + this.flowRecallService = new FlowRecallService(flowWorkRepository, flowRecordRepository, flowProcessRepository); + this.flowRemoveService = new FlowRemoveService(flowWorkRepository, flowRecordRepository, flowProcessRepository); + this.flowSaveService = new FlowSaveService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowProcessRepository); + this.flowTransferService = new FlowTransferService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowProcessRepository); + this.flowPostponedService = new FlowPostponedService(flowWorkRepository, flowRecordRepository, flowProcessRepository); + this.flowUrgeService = new FlowUrgeService(flowWorkRepository, flowRecordRepository, flowProcessRepository); } /** @@ -189,6 +189,18 @@ public FlowSubmitResult trySubmitFlow(long recordId, IFlowOperator currentOperat } + /** + * 获取流程执行节点 + * + * @param recordId + * @param currentOperator + * @return + */ + public FlowStepResult getFlowStep(long recordId, IBindData bindData, IFlowOperator currentOperator) { + FlowStepService flowStepService = new FlowStepService(recordId, null, currentOperator, bindData, flowServiceRepositoryHolder); + return flowStepService.getFlowStep(); + } + /** * 获取流程执行节点 * @@ -197,7 +209,7 @@ public FlowSubmitResult trySubmitFlow(long recordId, IFlowOperator currentOperat * @return */ public FlowStepResult getFlowStep(String workCode, IBindData bindData, IFlowOperator currentOperator) { - FlowStepService flowStepService = new FlowStepService(workCode, currentOperator, bindData, flowServiceRepositoryHolder); + FlowStepService flowStepService = new FlowStepService(0, workCode, currentOperator, bindData, flowServiceRepositoryHolder); return flowStepService.getFlowStep(); } @@ -230,10 +242,11 @@ public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBind /** * 唤醒流程 - * @param processId 流程实例id + * + * @param processId 流程实例id * @param currentOperator 当前操作者 */ - public void notifyFlow(String processId,IFlowOperator currentOperator) { + public void notifyFlow(String processId, IFlowOperator currentOperator) { FlowNotifyService flowNotifyService = new FlowNotifyService(processId, currentOperator, flowServiceRepositoryHolder); flowNotifyService.notifyFlow(); } @@ -263,7 +276,6 @@ public void recall(long recordId, IFlowOperator currentOperator) { } - /** * 删除流程 * diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java index c03833dd..6be110aa 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java @@ -12,12 +12,17 @@ import com.codingapi.springboot.flow.service.FlowNodeService; import com.codingapi.springboot.flow.service.FlowServiceRepositoryHolder; import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.utils.RandomGenerator; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; public class FlowStepService { private final FlowWork flowWork; + private final long recordId; + private final List flowRecords; private final IFlowOperator currentOperator; private final IBindData bindData; @@ -25,35 +30,59 @@ public class FlowStepService { private FlowNodeService flowNodeService; private FlowNode flowNode; + private FlowRecord currentFlowRecord; - public FlowStepService(String workCode, IFlowOperator currentOperator, IBindData bindData, FlowServiceRepositoryHolder flowServiceRepositoryHolder) { + public FlowStepService(long recordId,String workCode, IFlowOperator currentOperator, IBindData bindData, FlowServiceRepositoryHolder flowServiceRepositoryHolder) { + this.recordId = recordId; this.currentOperator = currentOperator; this.bindData = bindData; this.flowServiceRepositoryHolder = flowServiceRepositoryHolder; - this.flowWork = flowServiceRepositoryHolder.getFlowWorkRepository().getFlowWorkByCode(workCode); + if(this.recordId>0) { + this.currentFlowRecord = flowServiceRepositoryHolder.getFlowRecordRepository().getFlowRecordById(recordId); + this.flowRecords = flowServiceRepositoryHolder.getFlowRecordRepository().findFlowRecordByProcessId(currentFlowRecord.getProcessId()).stream().sorted(Comparator.comparingLong(FlowRecord::getId)).collect(Collectors.toList()); + this.flowWork = flowServiceRepositoryHolder.getFlowWorkRepository().getFlowWorkByCode(currentFlowRecord.getWorkCode()); + }else { + this.currentFlowRecord = null; + this.flowRecords = new ArrayList<>(); + this.flowWork = flowServiceRepositoryHolder.getFlowWorkRepository().getFlowWorkByCode(workCode); + } } public FlowStepResult getFlowStep() { FlowStepResult flowStepResult = new FlowStepResult(); - // 获取开始节点 - FlowNode start = flowWork.getStartNode(); - if (start == null) { - throw new IllegalArgumentException("start node not found"); - } - this.flowNode = start; // 设置开始流程的上一个流程id long preId = 0; + if(currentFlowRecord==null) { + // 获取开始节点 + FlowNode start = flowWork.getStartNode(); + if (start == null) { + throw new IllegalArgumentException("start node not found"); + } + preId = 0; + this.flowNode = start; + }else { + for(FlowRecord flowRecord : flowRecords) { + FlowNode flowNode = this.flowWork.getNodeByCode(flowRecord.getNodeCode()); + List operators = new ArrayList<>(); + if(flowRecord.getCurrentOperator()!=null) { + operators.add(flowRecord.getCurrentOperator()); + } + boolean isDone =flowRecord.isDone() || flowRecord.getOpinion().isCirculate(); + flowStepResult.addFlowNode(flowNode,isDone, operators); + } + FlowRecord lastRecord = this.flowRecords.get(this.flowRecords.size()-1); + this.flowNode = this.flowWork.getNodeByCode(lastRecord.getNodeCode()); + preId = lastRecord.getId(); + } // 创建流程id - String processId = "flow_" + System.currentTimeMillis(); - - List historyRecords = new ArrayList<>(); + String processId = "flow_" + RandomGenerator.generateUUID(); FlowOperatorRepository flowOperatorRepository = flowServiceRepositoryHolder.getFlowOperatorRepository(); FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); - + List historyRecords = new ArrayList<>(); BindDataSnapshot snapshot = new BindDataSnapshot(bindData); flowNodeService = new FlowNodeService(flowOperatorRepository, flowRecordRepository, @@ -67,15 +96,19 @@ public FlowStepResult getFlowStep() { processId, preId); - flowNodeService.setNextNode(start); + flowNodeService.setNextNode(this.flowNode); - this.flowNode = start; - flowStepResult.addFlowNode(this.flowNode, this.flowNodeService.loadNextNodeOperators()); + if(currentFlowRecord==null) { + flowStepResult.addFlowNode(this.flowNode, false, this.flowNodeService.loadNextNodeOperators()); + } do { flowNodeService.loadNextPassNode(this.flowNode); this.flowNode = flowNodeService.getNextNode(); - flowStepResult.addFlowNode(this.flowNode, this.flowNodeService.loadNextNodeOperators()); + + boolean isFinish = currentFlowRecord != null && currentFlowRecord.isFinish(); + + flowStepResult.addFlowNode(this.flowNode,isFinish, this.flowNodeService.loadNextNodeOperators()); } while (!flowNode.isOverNode()); return flowStepResult; diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index fcc55248..7e74cfce 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.6 + 2.10.7 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index ec4d5744..e1784ca5 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.6 + 2.10.7 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 266fc333..0cd411c3 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.6 +CodingApi SpringBoot-Starter 2.10.7 springboot version (${spring-boot.version}) ------------------------------------------------------ From 94f7d2d038a44e31e19de859c6b559e019ba5071 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 4 Jul 2025 10:06:45 +0800 Subject: [PATCH 104/129] fix #119 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/event/FlowApprovalEvent.java | 2 ++ .../springboot/flow/service/FlowService.java | 10 ++++++---- .../flow/service/impl/FlowRecallService.java | 10 +++++++++- .../flow/service/impl/FlowRemoveService.java | 12 ++++++++++-- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 11 files changed, 34 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index 72aaab49..c0198a4c 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.7 + 2.10.8 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index e5f9765d..cec41887 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.7 + 2.10.8 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 02221020..4831375c 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.7 + 2.10.8 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 25670f2a..20c3ec9b 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.7 + 2.10.8 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java index d6b8f406..ff4043cf 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java @@ -36,6 +36,8 @@ public class FlowApprovalEvent implements ISyncEvent { public static final int STATE_CIRCULATE = 9; // 保存 public static final int STATE_SAVE = 10; + // 删除 + public static final int STATE_DELETE = 11; private final int state; diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index 3990d679..861af676 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -41,8 +41,8 @@ public FlowService(FlowWorkRepository flowWorkRepository, this.flowServiceRepositoryHolder = new FlowServiceRepositoryHolder(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository, flowBackupRepository); this.flowDetailService = new FlowDetailService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowOperatorRepository, flowProcessRepository); this.flowCustomEventService = new FlowCustomEventService(flowWorkRepository, flowRecordRepository, flowProcessRepository); - this.flowRecallService = new FlowRecallService(flowWorkRepository, flowRecordRepository, flowProcessRepository); - this.flowRemoveService = new FlowRemoveService(flowWorkRepository, flowRecordRepository, flowProcessRepository); + this.flowRecallService = new FlowRecallService(flowWorkRepository, flowRecordRepository, flowProcessRepository,flowBindDataRepository); + this.flowRemoveService = new FlowRemoveService(flowWorkRepository, flowRecordRepository, flowProcessRepository,flowBindDataRepository); this.flowSaveService = new FlowSaveService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowProcessRepository); this.flowTransferService = new FlowTransferService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowProcessRepository); this.flowPostponedService = new FlowPostponedService(flowWorkRepository, flowRecordRepository, flowProcessRepository); @@ -57,11 +57,13 @@ public FlowService(FlowWorkRepository flowWorkRepository, * @return 流程详情 */ public FlowDetail detail(long recordId, String workCode, IFlowOperator currentOperator) { + if (recordId > 0) { + return flowDetailService.detail(recordId, currentOperator); + } if (StringUtils.hasText(workCode)) { return flowDetailService.detail(workCode, currentOperator); - } else { - return flowDetailService.detail(recordId, currentOperator); } + return null; } /** diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java index 124f48b8..352da79e 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java @@ -1,8 +1,11 @@ package com.codingapi.springboot.flow.service.impl; +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.IBindData; import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.event.FlowApprovalEvent; import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowBindDataRepository; import com.codingapi.springboot.flow.repository.FlowProcessRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; import com.codingapi.springboot.flow.repository.FlowWorkRepository; @@ -22,6 +25,7 @@ public class FlowRecallService { private final FlowWorkRepository flowWorkRepository; private final FlowRecordRepository flowRecordRepository; private final FlowProcessRepository flowProcessRepository; + private final FlowBindDataRepository flowBindDataRepository; /** * 撤回流程 @@ -47,6 +51,8 @@ public void recall(long recordId, IFlowOperator currentOperator) { // 下一流程的流程记录 List childrenRecords = flowRecordRepository.findFlowRecordByPreId(recordId); + + BindDataSnapshot bindDataSnapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); // 下一流程均为办理且未读 // 如果是在开始节点撤销,则直接删除 @@ -71,6 +77,8 @@ public void recall(long recordId, IFlowOperator currentOperator) { flowRecordRepository.delete(childrenRecords); } - EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_RECALL, flowRecord, currentOperator, flowWork, null), true); + IBindData bindData = bindDataSnapshot.toBindData(); + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_RECALL, flowRecord, currentOperator, flowWork, bindData), true); } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java index 82c42198..1aaed28a 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java @@ -1,9 +1,12 @@ package com.codingapi.springboot.flow.service.impl; +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.IBindData; import com.codingapi.springboot.flow.domain.FlowNode; import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.event.FlowApprovalEvent; import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowBindDataRepository; import com.codingapi.springboot.flow.repository.FlowProcessRepository; import com.codingapi.springboot.flow.repository.FlowRecordRepository; import com.codingapi.springboot.flow.repository.FlowWorkRepository; @@ -23,7 +26,7 @@ public class FlowRemoveService { private final FlowWorkRepository flowWorkRepository; private final FlowRecordRepository flowRecordRepository; private final FlowProcessRepository flowProcessRepository; - + private final FlowBindDataRepository flowBindDataRepository; /** * 删除流程 @@ -44,6 +47,7 @@ public void remove(long recordId, IFlowOperator currentOperator) { flowRecordVerifyService.loadFlowNode(); flowRecordVerifyService.verifyFlowRecordNotFinish(); flowRecordVerifyService.verifyFlowRecordIsTodo(); + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); FlowNode flowNode = flowRecordVerifyService.getFlowNode(); FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); @@ -51,8 +55,12 @@ public void remove(long recordId, IFlowOperator currentOperator) { throw new IllegalArgumentException("flow record not remove"); } - flowProcessRepository.deleteByProcessId(flowRecord.getProcessId()); + BindDataSnapshot bindDataSnapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + IBindData bindData = bindDataSnapshot.toBindData(); + flowProcessRepository.deleteByProcessId(flowRecord.getProcessId()); flowRecordRepository.deleteByProcessId(flowRecord.getProcessId()); + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_DELETE, flowRecord, currentOperator, flowWork, bindData), true); } } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 7e74cfce..9450019e 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.7 + 2.10.8 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index e1784ca5..73fe02ff 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.7 + 2.10.8 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 0cd411c3..290703fc 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.7 +CodingApi SpringBoot-Starter 2.10.8 springboot version (${spring-boot.version}) ------------------------------------------------------ From 3d94667782226ba606862dcd23b2661b0262c24d Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 4 Jul 2025 12:09:11 +0800 Subject: [PATCH 105/129] fix #123 --- .../springboot/flow/em/FlowType.java | 6 +- .../flow/event/FlowApprovalEvent.java | 16 ++ .../springboot/flow/record/FlowProcess.java | 14 ++ .../springboot/flow/record/FlowRecord.java | 11 + .../repository/FlowProcessRepository.java | 2 +- .../springboot/flow/service/FlowService.java | 27 +++ .../flow/service/impl/FlowBackService.java | 101 +++++++++ .../flow/service/impl/FlowRecallService.java | 13 +- .../flow/service/impl/FlowRemoveService.java | 14 +- .../flow/service/impl/FlowVoidedService.java | 82 +++++++ .../repository/FlowProcessRepositoryImpl.java | 10 +- .../repository/FlowRecordRepositoryImpl.java | 106 ++++++--- .../springboot/flow/test/FlowBackTest.java | 207 ++++++++++++++++++ .../springboot/flow/test/FlowVoidedTest.java | 189 ++++++++++++++++ 14 files changed, 757 insertions(+), 41 deletions(-) create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowBackService.java create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowVoidedService.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowBackTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowVoidedTest.java diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java index 5e36e57b..930eb03b 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java @@ -24,7 +24,11 @@ public enum FlowType { /** * 等待执行 */ - WAITING; + WAITING, + /** + * 删除 + */ + DELETE; public static FlowType parser(String type){ diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java index ff4043cf..fb160551 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java @@ -38,6 +38,10 @@ public class FlowApprovalEvent implements ISyncEvent { public static final int STATE_SAVE = 10; // 删除 public static final int STATE_DELETE = 11; + // 退回 + public static final int STATE_BACK = 12; + // 作废 + public static final int STATE_VOIDED = 13; private final int state; @@ -110,4 +114,16 @@ public boolean isRecall() { public boolean isFinish() { return state == STATE_FINISH; } + + public boolean isDelete() { + return state == STATE_DELETE; + } + + public boolean isVoided() { + return state == STATE_VOIDED; + } + + public boolean isBack() { + return state == STATE_BACK; + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowProcess.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowProcess.java index b8a4f975..46fcc892 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowProcess.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowProcess.java @@ -33,10 +33,24 @@ public class FlowProcess { private long createOperatorId; + /** + * 是否作废 + */ + private boolean voided; + + /** + * 作废流程 + */ + public void voided(){ + this.voided = true; + } + + public FlowProcess(long backupId, IFlowOperator createOperator) { this.processId = RandomGenerator.generateUUID(); this.createTime = System.currentTimeMillis(); this.backupId = backupId; this.createOperatorId = createOperator.getUserId(); + this.voided = false; } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java index ecd28cb9..75c54ceb 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -395,6 +395,13 @@ public void recall() { this.updateTime = System.currentTimeMillis(); } + /** + * 删除流程 + */ + public void delete() { + this.flowType = FlowType.DELETE; + this.updateTime = System.currentTimeMillis(); + } /** * 复制流程记录 @@ -430,6 +437,10 @@ public FlowRecord copy() { return record; } + public boolean isDelete() { + return this.flowType == FlowType.DELETE; + } + /** * 是否超时 diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java index acf8cfe1..a0d23ef9 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java @@ -10,9 +10,9 @@ public interface FlowProcessRepository { void save(FlowProcess flowProcess); - FlowWork getFlowWorkByProcessId(String processId); + FlowProcess getFlowProcessByProcessId(String processId); void deleteByProcessId(String processId); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index 861af676..103178c2 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -28,6 +28,8 @@ public class FlowService { private final FlowTransferService flowTransferService; private final FlowPostponedService flowPostponedService; private final FlowUrgeService flowUrgeService; + private final FlowVoidedService flowVoidedService; + private final FlowBackService flowBackService; private final FlowServiceRepositoryHolder flowServiceRepositoryHolder; @@ -47,6 +49,8 @@ public FlowService(FlowWorkRepository flowWorkRepository, this.flowTransferService = new FlowTransferService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, flowProcessRepository); this.flowPostponedService = new FlowPostponedService(flowWorkRepository, flowRecordRepository, flowProcessRepository); this.flowUrgeService = new FlowUrgeService(flowWorkRepository, flowRecordRepository, flowProcessRepository); + this.flowVoidedService = new FlowVoidedService(flowWorkRepository, flowRecordRepository, flowProcessRepository, flowBindDataRepository); + this.flowBackService = new FlowBackService(flowWorkRepository, flowRecordRepository, flowProcessRepository, flowBindDataRepository); } /** @@ -287,4 +291,27 @@ public void recall(long recordId, IFlowOperator currentOperator) { public void remove(long recordId, IFlowOperator currentOperator) { flowRemoveService.remove(recordId, currentOperator); } + + + /** + * 作废流程 + * + * @param processId 流程processId + * @param currentOperator 当前操作者 + */ + public void voided(String processId, IFlowOperator currentOperator) { + flowVoidedService.voided(processId, currentOperator); + } + + + /** + * 退回流程 + * + * @param processId 流程processId + * @param backNodeCode 退回节点编码 + * @param currentOperator 当前操作者 + */ + public void back(String processId, String backNodeCode, IFlowOperator currentOperator) { + flowBackService.back(processId, backNodeCode, currentOperator); + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowBackService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowBackService.java new file mode 100644 index 00000000..0e4514da --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowBackService.java @@ -0,0 +1,101 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.record.FlowProcess; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowBindDataRepository; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 流程退回服务(流程管理员操作) + */ +@Transactional +@AllArgsConstructor +public class FlowBackService { + + private final FlowWorkRepository flowWorkRepository; + private final FlowRecordRepository flowRecordRepository; + private final FlowProcessRepository flowProcessRepository; + private final FlowBindDataRepository flowBindDataRepository; + + + /** + * 退回流程 + * + * @param processId 流程processId + * @param backNodeCode 退回节点编码 + * @param currentOperator 当前操作者 + */ + public void back(String processId, String backNodeCode, IFlowOperator currentOperator) { + if (!currentOperator.isFlowManager()) { + throw new IllegalArgumentException("current operator not flow manager"); + } + + FlowProcess flowProcess = flowProcessRepository.getFlowProcessByProcessId(processId); + if (flowProcess.isVoided()) { + throw new IllegalArgumentException("flow process already voided"); + } + + List historyRecords = flowRecordRepository + .findFlowRecordByProcessId(processId) + .stream() + .sorted(Comparator.comparingLong(FlowRecord::getId)) + .collect(Collectors.toList()); + + for (FlowRecord flowRecord : historyRecords) { + if (flowRecord.isFinish()) { + throw new IllegalArgumentException("flow record already finish"); + } + } + + if (historyRecords.isEmpty()) { + throw new IllegalArgumentException("flow record not found"); + } + + List historyNodeCodes = historyRecords.stream() + .map(FlowRecord::getNodeCode) + .distinct() + .collect(Collectors.toList()); + + if (!historyNodeCodes.contains(backNodeCode)) { + throw new IllegalArgumentException("flow node code not found"); + } + + FlowRecord beginRecord = historyRecords.get(0); + for (FlowRecord flowRecord : historyRecords) { + if(flowRecord.getNodeCode().equals(backNodeCode)){ + beginRecord = flowRecord; + } + } + + for (FlowRecord flowRecord : historyRecords) { + if(flowRecord.getId()> beginRecord.getId() ){ + flowRecord.delete(); + }else { + if(flowRecord.getNodeCode().equals(beginRecord.getNodeCode())){ + flowRecord.recall(); + } + } + } + + flowRecordRepository.save(historyRecords); + + FlowWork flowWork = flowWorkRepository.getFlowWorkByCode(beginRecord.getWorkCode()); + IBindData bindData = flowBindDataRepository.getBindDataSnapshotById(beginRecord.getSnapshotId()).toBindData(); + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_BACK, beginRecord, currentOperator, flowWork, bindData), true); + + } +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java index 352da79e..ba6849ee 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java @@ -15,7 +15,7 @@ import lombok.AllArgsConstructor; import org.springframework.transaction.annotation.Transactional; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; @Transactional @@ -53,6 +53,7 @@ public void recall(long recordId, IFlowOperator currentOperator) { List childrenRecords = flowRecordRepository.findFlowRecordByPreId(recordId); BindDataSnapshot bindDataSnapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + // 下一流程均为办理且未读 // 如果是在开始节点撤销,则直接删除 @@ -60,7 +61,9 @@ public void recall(long recordId, IFlowOperator currentOperator) { if (!childrenRecords.isEmpty()) { throw new IllegalArgumentException("flow record not recall"); } - flowRecordRepository.delete(Collections.singletonList(flowRecord)); + List flowRecords = new ArrayList<>(); + flowRecords.add(flowRecord); + flowRecordRepository.delete(flowRecords); } else { // 如果是在中间节点撤销,则需要判断是否所有的子流程都是未读状态 if (childrenRecords.isEmpty()) { @@ -74,9 +77,11 @@ public void recall(long recordId, IFlowOperator currentOperator) { flowRecord.recall(); flowRecordRepository.update(flowRecord); - flowRecordRepository.delete(childrenRecords); + for(FlowRecord childrenRecord : childrenRecords) { + childrenRecord.delete(); + } + flowRecordRepository.save(childrenRecords); } - IBindData bindData = bindDataSnapshot.toBindData(); EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_RECALL, flowRecord, currentOperator, flowWork, bindData), true); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java index 1aaed28a..92a6a776 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java @@ -5,6 +5,7 @@ import com.codingapi.springboot.flow.domain.FlowNode; import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.record.FlowProcess; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.FlowBindDataRepository; import com.codingapi.springboot.flow.repository.FlowProcessRepository; @@ -16,7 +17,6 @@ import lombok.AllArgsConstructor; import org.springframework.transaction.annotation.Transactional; -import java.util.Collections; import java.util.List; @Transactional @@ -54,12 +54,18 @@ public void remove(long recordId, IFlowOperator currentOperator) { if(!flowNode.isStartNode()){ throw new IllegalArgumentException("flow record not remove"); } - BindDataSnapshot bindDataSnapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); IBindData bindData = bindDataSnapshot.toBindData(); - flowProcessRepository.deleteByProcessId(flowRecord.getProcessId()); - flowRecordRepository.deleteByProcessId(flowRecord.getProcessId()); + FlowProcess flowProcess = flowProcessRepository.getFlowProcessByProcessId(flowRecord.getProcessId()); + flowProcess.voided(); + flowProcessRepository.save(flowProcess); + + List historyRecords = flowRecordRepository.findFlowRecordByProcessId(flowRecord.getProcessId()); + for (FlowRecord record : historyRecords) { + record.delete(); + } + flowRecordRepository.save(historyRecords); EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_DELETE, flowRecord, currentOperator, flowWork, bindData), true); } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowVoidedService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowVoidedService.java new file mode 100644 index 00000000..059cff2d --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowVoidedService.java @@ -0,0 +1,82 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.record.FlowProcess; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowBindDataRepository; +import com.codingapi.springboot.flow.repository.FlowProcessRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.repository.FlowWorkRepository; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 流程作废服务(流程管理员操作) + */ +@Transactional +@AllArgsConstructor +public class FlowVoidedService { + + private final FlowWorkRepository flowWorkRepository; + private final FlowRecordRepository flowRecordRepository; + private final FlowProcessRepository flowProcessRepository; + private final FlowBindDataRepository flowBindDataRepository; + + + /** + * 作废流程 + * + * @param processId 流程processId + * @param currentOperator 当前操作者 + */ + public void voided(String processId, IFlowOperator currentOperator) { + if (!currentOperator.isFlowManager()) { + throw new IllegalArgumentException("current operator not flow manager"); + } + + FlowProcess flowProcess = flowProcessRepository.getFlowProcessByProcessId(processId); + if(flowProcess.isVoided()){ + throw new IllegalArgumentException("flow process already voided"); + } + flowProcess.voided(); + flowProcessRepository.save(flowProcess); + + FlowRecord currentRecord = null; + List flowRecords = flowRecordRepository.findFlowRecordByProcessId(processId); + if (!flowRecords.isEmpty()) { + for (FlowRecord flowRecord : flowRecords) { + if (flowRecord.isFinish()) { + throw new IllegalArgumentException("flow record already finish"); + } + flowRecord.delete(); + if(currentRecord==null || flowRecord.getId()> currentRecord.getId()){ + currentRecord = flowRecord; + } + } + } + flowRecordRepository.save(flowRecords); + + FlowWork flowWork = null; + + IBindData bindData = null; + if (currentRecord != null) { + // 删除流程绑定数据 + BindDataSnapshot dataSnapshot = flowBindDataRepository.getBindDataSnapshotById(currentRecord.getSnapshotId()); + if (dataSnapshot != null) { + bindData = dataSnapshot.toBindData(); + } + flowWork = flowWorkRepository.getFlowWorkByCode(currentRecord.getWorkCode()); + } + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_VOIDED, currentRecord, currentOperator, flowWork, bindData), true); + + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java index b128f599..e1d96880 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java @@ -27,7 +27,10 @@ public void save(FlowProcess flowProcess) { @Override public FlowWork getFlowWorkByProcessId(String processId) { - FlowProcess process = cache.stream().filter(flowProcess -> flowProcess.getProcessId().equals(processId)).findFirst().orElse(null); + FlowProcess process = cache.stream() + .filter(flowProcess -> flowProcess.getProcessId().equals(processId)) + .filter(flowProcess -> !flowProcess.isVoided()) + .findFirst().orElse(null); if (process == null) { return null; } @@ -35,6 +38,11 @@ public FlowWork getFlowWorkByProcessId(String processId) { return flowBackup.resume(userRepository); } + @Override + public FlowProcess getFlowProcessByProcessId(String processId) { + return cache.stream().filter(flowProcess -> flowProcess.getProcessId().equals(processId)).findFirst().orElse(null); + } + @Override public void deleteByProcessId(String processId) { cache.removeIf(flowProcess -> flowProcess.getProcessId().equals(processId)); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java index 603d5e42..f5d290a6 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java @@ -26,7 +26,10 @@ public void save(List records) { @Override public FlowRecord getFlowRecordById(long id) { - return cache.stream().filter(record -> record.getId() == id).findFirst().orElse(null); + return cache.stream() + .filter(record -> record.getId() == id) + .filter(record -> !record.isDelete()) + .findFirst().orElse(null); } @@ -40,7 +43,10 @@ public void update(FlowRecord flowRecord) { @Override public List findFlowRecordByPreId(long preId) { - return cache.stream().filter(record -> record.getPreId() == preId).collect(Collectors.toList()); + return cache.stream() + .filter(record -> record.getPreId() == preId) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); } @Override @@ -51,12 +57,15 @@ public List findMergeFlowRecordById(String workCode, String nodeCode && record.getNodeCode().equals(nodeCode) && record.isMergeable() ) + .filter(record -> !record.isDelete()) .collect(Collectors.toList()); } @Override public List findFlowRecordByProcessId(String processId) { - return cache.stream().filter(record -> record.getProcessId().equals(processId)) + return cache.stream(). + filter(record -> record.getProcessId().equals(processId)) + .filter(record -> !record.isDelete()) .sorted((o1, o2) -> (int) (o1.getCreateTime() - o2.getCreateTime())) .collect(Collectors.toList()); } @@ -67,97 +76,133 @@ public List findTodoFlowRecordByProcessId(String processId) { } public Page findAll(PageRequest pageRequest) { - return new PageImpl<>(cache); + return new PageImpl<>(cache.stream() + .filter(record -> !record.isDelete()) + .collect(Collectors.toList())); } @Override public Page findDoneByOperatorId(long operatorId, PageRequest pageRequest) { - List flowRecords = cache.stream().filter(record -> record.isDone() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + List flowRecords = cache.stream() + .filter(record -> record.isDone() && record.getCurrentOperator().getUserId() == operatorId) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @Override public Page findUnReadByOperatorId(long operatorId, PageRequest pageRequest) { - List flowRecords = cache.stream().filter(record -> record.isUnRead() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + List flowRecords = cache.stream() + .filter(record -> record.isUnRead() && record.getCurrentOperator().getUserId() == operatorId) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @Override public Page findUnReadByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { - List flowRecords = cache.stream().filter(record -> record.isUnRead() && record.getWorkCode().equals(workCode) && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + List flowRecords = cache.stream() + .filter(record -> record.isUnRead() && record.getWorkCode().equals(workCode) && record.getCurrentOperator().getUserId() == operatorId) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @Override public Page findDoneByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { - List flowRecords = cache.stream().filter(record -> record.isDone() - && record.getCurrentOperator().getUserId() == operatorId - && record.getWorkCode().equals(workCode) - ).collect(Collectors.toList()); + List flowRecords = cache.stream(). + filter(record -> record.isDone() + && record.getCurrentOperator().getUserId() == operatorId + && record.getWorkCode().equals(workCode) + ) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @Override public Page findInitiatedByOperatorId(long operatorId, PageRequest pageRequest) { - List flowRecords = cache.stream().filter(record -> record.isInitiated() && record.getCreateOperator().getUserId() == operatorId).collect(Collectors.toList()); + List flowRecords = cache.stream() + .filter(record -> record.isInitiated() && record.getCreateOperator().getUserId() == operatorId) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @Override public Page findInitiatedByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { - List flowRecords = cache.stream().filter( - record -> record.isInitiated() - && record.getCreateOperator().getUserId() == operatorId - && record.getWorkCode().equals(workCode) - ).collect(Collectors.toList()); + List flowRecords = cache.stream() + .filter( + record -> record.isInitiated() + && record.getCreateOperator().getUserId() == operatorId + && record.getWorkCode().equals(workCode) + ) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @Override public Page findTodoByOperatorId(long operatorId, PageRequest pageRequest) { - List flowRecords = cache.stream().filter(record -> record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + List flowRecords = cache.stream() + .filter(record -> record.isTodo() && record.getCurrentOperator().getUserId() == operatorId) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @Override public Page findTodoByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { - List flowRecords = cache.stream().filter(record -> record.isTodo() && record.getCurrentOperator().getUserId() == operatorId && record.getWorkCode().equals(workCode)).collect(Collectors.toList()); + List flowRecords = cache.stream() + .filter(record -> record.isTodo() && record.getCurrentOperator().getUserId() == operatorId && record.getWorkCode().equals(workCode)) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @Override public Page findTimeoutTodoByOperatorId(long operatorId, PageRequest pageRequest) { - List flowRecords = cache.stream().filter(record -> record.isTimeout() && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + List flowRecords = cache.stream() + .filter(record -> record.isTimeout() && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @Override public Page findTimeoutTodoByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { - List flowRecords = cache.stream().filter( - record -> record.isTimeout() - && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId - && record.getWorkCode().equals(workCode) - ).collect(Collectors.toList()); + List flowRecords = cache.stream() + .filter( + record -> record.isTimeout() + && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId + && record.getWorkCode().equals(workCode) + ).filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @Override public Page findPostponedTodoByOperatorId(long operatorId, PageRequest pageRequest) { - List flowRecords = cache.stream().filter(record -> record.isPostponed() && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId).collect(Collectors.toList()); + List flowRecords = cache.stream() + .filter(record -> record.isPostponed() && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @Override public Page findPostponedTodoByOperatorId(long operatorId, String workCode, PageRequest pageRequest) { - List flowRecords = cache.stream().filter(record -> record.isPostponed() - && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId - && record.getWorkCode().equals(workCode) - ).collect(Collectors.toList()); + List flowRecords = cache.stream() + .filter(record -> record.isPostponed() + && record.isTodo() && record.getCurrentOperator().getUserId() == operatorId + && record.getWorkCode().equals(workCode) + ).filter(record -> !record.isDelete()) + .collect(Collectors.toList()); return new PageImpl<>(flowRecords); } @@ -165,6 +210,7 @@ public Page findPostponedTodoByOperatorId(long operatorId, String wo public void finishFlowRecordByProcessId(String processId) { cache.stream() .filter(record -> record.getProcessId().equals(processId)) + .filter(record -> !record.isDelete()) .forEach(FlowRecord::finish); } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowBackTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowBackTest.java new file mode 100644 index 00000000..022d7790 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowBackTest.java @@ -0,0 +1,207 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class FlowBackTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository, userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository, flowProcessRepository, flowBackupRepository); + + /** + * 流程退回测试,结束的流程作废失败 + */ + @Test + void back1() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮",true); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .skipIfSameApprover(true) + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交委托dept部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + assertThrows(IllegalArgumentException.class,()->{ + // 退回流程 + flowService.back(deptTodo.getProcessId(),"start",boss); + }); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + + } + + + /** + * 流程退回测试,在结束节点前退回流程 + */ + @Test + void back2() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮",true); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .skipIfSameApprover(true) + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交委托dept部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + // 流程作废 + flowService.back(deptTodo.getProcessId(),"start",boss); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(1, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交委托dept部门经理的审批 + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowVoidedTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowVoidedTest.java new file mode 100644 index 00000000..83215ef0 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowVoidedTest.java @@ -0,0 +1,189 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class FlowVoidedTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository, userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository, flowProcessRepository, flowBackupRepository); + + + /** + * 流程作废测试,结束的流程作废失败 + */ + @Test + void voided1() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮",true); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .skipIfSameApprover(true) + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交委托dept部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + assertThrows(IllegalArgumentException.class,()->{ + // 作废流程 + flowService.voided(deptTodo.getProcessId(),boss); + }); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + + } + + + /** + * 流程作废测试,在结束节点前作废流程 + */ + @Test + void voided2() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮",true); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .skipIfSameApprover(true) + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交委托dept部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + // 流程作废 + flowService.voided(deptTodo.getProcessId(),boss); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(0, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(0, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isDelete)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(2, snapshots.size()); + + } +} From 45d2b5d56048c4db4ec46e21bf128bed8433eccb Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 4 Jul 2025 17:45:02 +0800 Subject: [PATCH 106/129] fix org.sonatype.plugins --- event.md | 36 +++++++++++++++++++ pom.xml | 25 +++++++++---- springboot-starter-data-authorization/pom.xml | 1 + springboot-starter-data-fast/pom.xml | 2 ++ 4 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 event.md diff --git a/event.md b/event.md new file mode 100644 index 00000000..1456cd02 --- /dev/null +++ b/event.md @@ -0,0 +1,36 @@ +# 流程事件触发机制 + +* 发起流程 +事件: CREATE TODO SAVE +* 保存流程 +事件: SAVE +* 提交流程 +事件: PASS TODO(下一个节点记录数据) +* 驳回流程 +事件: REJECT TODO(下一个节点记录数据) +* 撤回流程 +事件: RECALL +* 删除流程 +事件: DELETE +* 作废流程 +事件: VOIDED +* 退回流程 +事件:BACK +* 流程结束 +事件: FINISH +* 转办流程 +事件:TRANSFER TODO(下一个节点记录数据) +* 唤醒流程 +事件: TODO +* 催办流程 +事件: URGE 当前审批人 +* 延期流程 +事件: 未发送事件 + +--------------------- +自定义事件:是前端自己触法的逻辑 +自定义接口:是执行后端按钮配置的脚本 + +在开始节点点击任何按钮的时候,若流程不存在则会先执行流程的创建,然后再执行对应的按钮操作。 + + diff --git a/pom.xml b/pom.xml index c0198a4c..48000bca 100644 --- a/pom.xml +++ b/pom.xml @@ -378,19 +378,30 @@ + + + + + + + + + + + + - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.13 + org.sonatype.central + central-publishing-maven-plugin + 0.8.0 true - ossrh - https://oss.sonatype.org/ - true + central + true + published - org.apache.maven.plugins maven-javadoc-plugin diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index cec41887..c510b27a 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -9,6 +9,7 @@ 2.10.8 + springboot-starter-data-authorization springboot-starter-data-authorization springboot-starter-data-authorization project for Spring Boot diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 4831375c..c577c008 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -9,7 +9,9 @@ 4.0.0 + springboot-starter-data-fast springboot-starter-data-fast + springboot-starter-data-fast project for Spring Boot 8 From 7ea56d853020b3fbc4feb34750592caab1cd2930 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 12 Jul 2025 12:01:28 +0800 Subject: [PATCH 107/129] fix #127 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../springboot/fast/jpa/JPAQuery.java | 18 + .../fast/jpa/map/MapViewResult.java | 1029 +++++++++++++++++ .../springboot/fast/jpa/map/QueryColumns.java | 53 + .../fast/jpa/map/QueryColumnsContext.java | 35 + .../jpa/repository/DynamicRepository.java | 10 + .../springboot/fast/UserRepositoryTest.java | 48 + springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 13 files changed, 1200 insertions(+), 7 deletions(-) create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/MapViewResult.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/QueryColumns.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/QueryColumnsContext.java diff --git a/pom.xml b/pom.xml index 48000bca..a92cc8f2 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.8 + 2.10.9 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index c510b27a..0db7a5d9 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.8 + 2.10.9 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index c577c008..c2db42c0 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.8 + 2.10.9 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java index aa1ddaff..269fc58f 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java @@ -1,5 +1,8 @@ package com.codingapi.springboot.fast.jpa; +import com.codingapi.springboot.fast.jpa.map.MapViewResult; +import com.codingapi.springboot.fast.jpa.map.QueryColumns; +import com.codingapi.springboot.fast.jpa.map.QueryColumnsContext; import lombok.AllArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -60,4 +63,19 @@ private long countQuery(String sql, Object... params) { return query.getSingleResult(); } + public Page pageMapQuery(QueryColumns columns, String sql, String countSql, PageRequest pageRequest, Object... params) { + String querySql = "select new com.codingapi.springboot.fast.jpa.map.MapViewResult('"+columns.getKey()+"',"+ String.join(",", columns.getColumnSql()) + ") " + sql; + String countQuerySql = "select count(1) " + countSql; + Page result = (Page) pageQuery(MapViewResult.class,querySql,countQuerySql,pageRequest,params); + QueryColumnsContext.getInstance().clearCache(columns.getKey()); + return result; + } + + public List listMapQuery(QueryColumns columns, String sql, Object... params) { + String querySql = "select new com.codingapi.springboot.fast.jpa.map.MapViewResult('"+columns.getKey()+"',"+ String.join(",", columns.getColumnSql()) + ") " + sql; + List result = listQuery(MapViewResult.class,querySql,params); + QueryColumnsContext.getInstance().clearCache(columns.getKey()); + return result; + } + } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/MapViewResult.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/MapViewResult.java new file mode 100644 index 00000000..36d36f93 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/MapViewResult.java @@ -0,0 +1,1029 @@ +package com.codingapi.springboot.fast.jpa.map; + +import java.util.HashMap; +import java.util.List; + +public class MapViewResult extends HashMap { + + public MapViewResult(String key, Object o1) { + this.build(key, o1); + } + + public MapViewResult(String key, Object o1, Object o2) { + this.build(key, o1, o2); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3) { + this.build(key, o1, o2, o3); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4) { + this.build(key, o1, o2, o3, o4); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5) { + this.build(key, o1, o2, o3, o4, o5); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6) { + this.build(key, o1, o2, o3, o4, o5, o6); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7) { + this.build(key, o1, o2, o3, o4, o5, o6, o7); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242, Object o243) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242, o243); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242, Object o243, Object o244) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242, o243, o244); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242, Object o243, Object o244, Object o245) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242, o243, o244, o245); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242, Object o243, Object o244, Object o245, Object o246) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242, o243, o244, o245, o246); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242, Object o243, Object o244, Object o245, Object o246, Object o247) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242, o243, o244, o245, o246, o247); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242, Object o243, Object o244, Object o245, Object o246, Object o247, Object o248) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242, o243, o244, o245, o246, o247, o248); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242, Object o243, Object o244, Object o245, Object o246, Object o247, Object o248, Object o249) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242, o243, o244, o245, o246, o247, o248, o249); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242, Object o243, Object o244, Object o245, Object o246, Object o247, Object o248, Object o249, Object o250) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242, o243, o244, o245, o246, o247, o248, o249, o250); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242, Object o243, Object o244, Object o245, Object o246, Object o247, Object o248, Object o249, Object o250, Object o251) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242, o243, o244, o245, o246, o247, o248, o249, o250, o251); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242, Object o243, Object o244, Object o245, Object o246, Object o247, Object o248, Object o249, Object o250, Object o251, Object o252) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242, o243, o244, o245, o246, o247, o248, o249, o250, o251, o252); + } + + public MapViewResult(String key, Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9, Object o10, Object o11, Object o12, Object o13, Object o14, Object o15, Object o16, Object o17, Object o18, Object o19, Object o20, Object o21, Object o22, Object o23, Object o24, Object o25, Object o26, Object o27, Object o28, Object o29, Object o30, Object o31, Object o32, Object o33, Object o34, Object o35, Object o36, Object o37, Object o38, Object o39, Object o40, Object o41, Object o42, Object o43, Object o44, Object o45, Object o46, Object o47, Object o48, Object o49, Object o50, Object o51, Object o52, Object o53, Object o54, Object o55, Object o56, Object o57, Object o58, Object o59, Object o60, Object o61, Object o62, Object o63, Object o64, Object o65, Object o66, Object o67, Object o68, Object o69, Object o70, Object o71, Object o72, Object o73, Object o74, Object o75, Object o76, Object o77, Object o78, Object o79, Object o80, Object o81, Object o82, Object o83, Object o84, Object o85, Object o86, Object o87, Object o88, Object o89, Object o90, Object o91, Object o92, Object o93, Object o94, Object o95, Object o96, Object o97, Object o98, Object o99, Object o100, Object o101, Object o102, Object o103, Object o104, Object o105, Object o106, Object o107, Object o108, Object o109, Object o110, Object o111, Object o112, Object o113, Object o114, Object o115, Object o116, Object o117, Object o118, Object o119, Object o120, Object o121, Object o122, Object o123, Object o124, Object o125, Object o126, Object o127, Object o128, Object o129, Object o130, Object o131, Object o132, Object o133, Object o134, Object o135, Object o136, Object o137, Object o138, Object o139, Object o140, Object o141, Object o142, Object o143, Object o144, Object o145, Object o146, Object o147, Object o148, Object o149, Object o150, Object o151, Object o152, Object o153, Object o154, Object o155, Object o156, Object o157, Object o158, Object o159, Object o160, Object o161, Object o162, Object o163, Object o164, Object o165, Object o166, Object o167, Object o168, Object o169, Object o170, Object o171, Object o172, Object o173, Object o174, Object o175, Object o176, Object o177, Object o178, Object o179, Object o180, Object o181, Object o182, Object o183, Object o184, Object o185, Object o186, Object o187, Object o188, Object o189, Object o190, Object o191, Object o192, Object o193, Object o194, Object o195, Object o196, Object o197, Object o198, Object o199, Object o200, Object o201, Object o202, Object o203, Object o204, Object o205, Object o206, Object o207, Object o208, Object o209, Object o210, Object o211, Object o212, Object o213, Object o214, Object o215, Object o216, Object o217, Object o218, Object o219, Object o220, Object o221, Object o222, Object o223, Object o224, Object o225, Object o226, Object o227, Object o228, Object o229, Object o230, Object o231, Object o232, Object o233, Object o234, Object o235, Object o236, Object o237, Object o238, Object o239, Object o240, Object o241, Object o242, Object o243, Object o244, Object o245, Object o246, Object o247, Object o248, Object o249, Object o250, Object o251, Object o252, Object o253) { + this.build(key, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32, o33, o34, o35, o36, o37, o38, o39, o40, o41, o42, o43, o44, o45, o46, o47, o48, o49, o50, o51, o52, o53, o54, o55, o56, o57, o58, o59, o60, o61, o62, o63, o64, o65, o66, o67, o68, o69, o70, o71, o72, o73, o74, o75, o76, o77, o78, o79, o80, o81, o82, o83, o84, o85, o86, o87, o88, o89, o90, o91, o92, o93, o94, o95, o96, o97, o98, o99, o100, o101, o102, o103, o104, o105, o106, o107, o108, o109, o110, o111, o112, o113, o114, o115, o116, o117, o118, o119, o120, o121, o122, o123, o124, o125, o126, o127, o128, o129, o130, o131, o132, o133, o134, o135, o136, o137, o138, o139, o140, o141, o142, o143, o144, o145, o146, o147, o148, o149, o150, o151, o152, o153, o154, o155, o156, o157, o158, o159, o160, o161, o162, o163, o164, o165, o166, o167, o168, o169, o170, o171, o172, o173, o174, o175, o176, o177, o178, o179, o180, o181, o182, o183, o184, o185, o186, o187, o188, o189, o190, o191, o192, o193, o194, o195, o196, o197, o198, o199, o200, o201, o202, o203, o204, o205, o206, o207, o208, o209, o210, o211, o212, o213, o214, o215, o216, o217, o218, o219, o220, o221, o222, o223, o224, o225, o226, o227, o228, o229, o230, o231, o232, o233, o234, o235, o236, o237, o238, o239, o240, o241, o242, o243, o244, o245, o246, o247, o248, o249, o250, o251, o252, o253); + } + + private void build(String key, Object... values) { + QueryColumns queryColumns = QueryColumnsContext.getInstance().getQueryColumns(key); + List columns = queryColumns.getColumnAlias(); + for (int i = 0; i < columns.size(); i++) { + String column = columns.get(i); + Object value = values[i]; + this.put(column, value); + } + } +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/QueryColumns.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/QueryColumns.java new file mode 100644 index 00000000..c63d0214 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/QueryColumns.java @@ -0,0 +1,53 @@ +package com.codingapi.springboot.fast.jpa.map; + +import com.codingapi.springboot.framework.utils.RandomGenerator; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +@Getter +public class QueryColumns { + private final String key; + private final List columns; + + QueryColumns() { + this.key = RandomGenerator.randomString(8); + this.columns = new ArrayList<>(); + } + + public QueryColumns addColumn(String column) { + this.columns.add(column); + return this; + } + + List getColumnAlias(){ + List columnAlias = new ArrayList<>(); + for (String column : columns) { + if(column.contains("as ") ) { + String[] parts = column.split("as "); + String alias = parts[parts.length - 1]; + columnAlias.add(alias.trim()); + continue; + } + if(column.contains("AS ") ) { + String[] parts = column.split("AS "); + String alias = parts[parts.length - 1]; + columnAlias.add(alias.trim()); + continue; + } + if(column.contains(".") ) { + String[] parts = column.split("\\."); + String alias = parts[parts.length - 1]; + columnAlias.add(alias.trim()); + continue; + } + columnAlias.add(column.trim()); + } + return columnAlias; + } + + public String getColumnSql() { + return String.join(",", columns); + } +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/QueryColumnsContext.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/QueryColumnsContext.java new file mode 100644 index 00000000..f2b8d50a --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/map/QueryColumnsContext.java @@ -0,0 +1,35 @@ +package com.codingapi.springboot.fast.jpa.map; + +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +@Getter +public class QueryColumnsContext { + private final Map cache = new HashMap<>(); + @Getter + private final static QueryColumnsContext instance = new QueryColumnsContext(); + + private QueryColumnsContext() { + + } + + public static QueryColumns build(String ... columns) { + QueryColumns mapColumn = new QueryColumns(); + for (String column : columns) { + mapColumn.addColumn(column); + } + QueryColumnsContext.getInstance().cache.put(mapColumn.getKey(), mapColumn); + return mapColumn; + } + + + QueryColumns getQueryColumns(String key) { + return this.cache.get(key); + } + + public void clearCache(String key) { + this.cache.remove(key); + } +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java index a2fe6c76..ae675698 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java @@ -2,6 +2,8 @@ import com.codingapi.springboot.fast.jpa.JpaQueryContext; import com.codingapi.springboot.fast.jpa.SQLBuilder; +import com.codingapi.springboot.fast.jpa.map.MapViewResult; +import com.codingapi.springboot.fast.jpa.map.QueryColumns; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.repository.NoRepositoryBean; @@ -40,4 +42,12 @@ default Page dynamicPageQuery(Class clazz, String sql, String countSql return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(clazz, sql, countSql, request, params); } + default Page dynamicMapPageQuery(QueryColumns columns, String sql, String countSql, PageRequest request, Object... params) { + return JpaQueryContext.getInstance().getJPAQuery().pageMapQuery(columns, sql, countSql, request, params); + } + + default List dynamicMapListQuery(QueryColumns columns, String sql, Object... params) { + return (List) JpaQueryContext.getInstance().getJPAQuery().listMapQuery(columns, sql, params); + } + } diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/UserRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/UserRepositoryTest.java index 1047c25b..8c25bb4b 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/UserRepositoryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/UserRepositoryTest.java @@ -3,6 +3,8 @@ import com.codingapi.springboot.fast.entity.Demo; import com.codingapi.springboot.fast.entity.Profile; import com.codingapi.springboot.fast.entity.User; +import com.codingapi.springboot.fast.jpa.map.MapViewResult; +import com.codingapi.springboot.fast.jpa.map.QueryColumnsContext; import com.codingapi.springboot.fast.repository.DemoRepository; import com.codingapi.springboot.fast.repository.ProfileRepository; import com.codingapi.springboot.fast.repository.UserRepository; @@ -13,6 +15,8 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.Page; +import java.util.List; + import static org.junit.jupiter.api.Assertions.assertTrue; @Slf4j @@ -59,6 +63,50 @@ void test1() { } + @Test + void testMapQuery() { + + Demo demo = new Demo(); + demo.setName("123"); + demoRepository.save(demo); + + + Profile profile = new Profile(); + profile.setDemo(demo); + profile.setName("123"); + profileRepository.save(profile); + + + User user = new User(); + user.setName("li"); + user.setProfile(profile); + userRepository.save(user); + + assertTrue(demo.getId() > 0); + assertTrue(user.getId() > 0); + + PageRequest request = new PageRequest(); + request.addFilter("profile.demo.id", 1); + + String querySql = "from User u where u.profile.demo.id = ?1"; + String countSQL = "from User u where u.profile.demo.id = ?1"; + Page page = + userRepository.dynamicMapPageQuery( + QueryColumnsContext.build("u.id as iii","u.name"), + querySql, + countSQL, request, 1); + List queryMaps = page.getContent(); + System.out.println(queryMaps); + + List list = + userRepository.dynamicMapListQuery( + QueryColumnsContext.build("u.id as iii","u.name"), + querySql, + 1); + System.out.println(list); + + } + @Test void test2() { diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 20c3ec9b..b8026c82 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.8 + 2.10.9 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 9450019e..f5db5a94 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.8 + 2.10.9 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 73fe02ff..bb058929 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.8 + 2.10.9 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 290703fc..16d4b943 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.8 +CodingApi SpringBoot-Starter 2.10.9 springboot version (${spring-boot.version}) ------------------------------------------------------ From bb754ddad0c51cf52ae40bcd66a2e67674101f80 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 14 Jul 2025 09:12:42 +0800 Subject: [PATCH 108/129] support SQLBuilder --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../springboot/fast/jdbc/JdbcQuery.java | 26 +++++++------- .../springboot/fast/jpa/JPAQuery.java | 35 +++++++++---------- .../springboot/fast/jpa/SQLBuilder.java | 29 ++++++++------- .../repository/DynamicNativeRepository.java | 8 ++--- .../jpa/repository/DynamicRepository.java | 23 ++++++------ springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 12 files changed, 69 insertions(+), 66 deletions(-) diff --git a/pom.xml b/pom.xml index a92cc8f2..824344fd 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.9 + 2.10.10 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 0db7a5d9..0c146ba7 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.9 + 2.10.10 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index c2db42c0..8901560b 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.9 + 2.10.10 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java index 0a3e8be0..b28743d4 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java @@ -38,49 +38,49 @@ public Map mapRow(ResultSet rs, int rowNum) throws SQLException } } - public List> queryForMapList(SQLBuilder builder) { + public List> queryForMapList(SQLBuilder builder) { return queryForMapList(builder.getSQL(), builder.getParams()); } public List> queryForMapList(String sql, Object... params) { - return jdbcTemplate.query(sql, params, new CamelCaseRowMapper()); + return jdbcTemplate.query(sql, new CamelCaseRowMapper(), params); } - public List queryForList(SQLBuilder builder) { - return (List) queryForList(builder.getSQL(), builder.getClazz(), builder.getParams()); + public List queryForList(SQLBuilder builder) { + return queryForList(builder.getSQL(), builder.getClazz(), builder.getParams()); } public List queryForList(String sql, Class clazz, Object... params) { - return jdbcTemplate.query(sql, params, new BeanPropertyRowMapper<>(clazz)); + return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(clazz), params); } - public Page queryForPage(SQLBuilder builder, PageRequest pageRequest) { - return (Page)queryForPage(builder.getSQL(), builder.getCountSQL(), builder.getClazz(), pageRequest, builder.getParams()); + public Page queryForPage(SQLBuilder builder, PageRequest pageRequest) { + return queryForPage(builder.getSQL(), builder.getCountSQL(), builder.getClazz(), pageRequest, builder.getParams()); } public Page queryForPage(String sql, String countSql, Class clazz, PageRequest pageRequest, Object... params) { - List list = jdbcTemplate.query(sql, params, new BeanPropertyRowMapper<>(clazz)); + List list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(clazz), params); long count = this.countQuery(countSql, params); return new PageImpl<>(list, pageRequest, count); } public Page queryForPage(String sql, Class clazz, PageRequest pageRequest, Object... params) { - String countSql = "select count(1) " + sql; + String countSql = "SELECT COUNT(1) " + sql; return this.queryForPage(sql, countSql, clazz, pageRequest, params); } - public Page> queryForMapPage(SQLBuilder builder, PageRequest pageRequest) { + public Page> queryForMapPage(SQLBuilder builder, PageRequest pageRequest) { return queryForMapPage(builder.getSQL(), builder.getCountSQL(), pageRequest, builder.getParams()); } public Page> queryForMapPage(String sql, String countSql, PageRequest pageRequest, Object... params) { - List> list = jdbcTemplate.query(sql, params, new CamelCaseRowMapper()); + List> list = jdbcTemplate.query(sql, new CamelCaseRowMapper(), params); long count = this.countQuery(countSql, params); return new PageImpl<>(list, pageRequest, count); } public Page> queryForMapPage(String sql, PageRequest pageRequest, Object... params) { - String countSql = "select count(1) " + sql; + String countSql = "SELECT COUNT(1) " + sql; return this.queryForMapPage(sql, countSql, pageRequest, params); } @@ -92,6 +92,6 @@ private long countQuery(String sql, Object... params) { if (paramsLength > countSqlParamsLength) { System.arraycopy(params, 0, newParams, 0, countSqlParamsLength); } - return jdbcTemplate.queryForObject(sql, newParams, Long.class); + return jdbcTemplate.queryForObject(sql, Long.class, newParams); } } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java index 269fc58f..3ad16091 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java @@ -1,8 +1,8 @@ package com.codingapi.springboot.fast.jpa; -import com.codingapi.springboot.fast.jpa.map.MapViewResult; -import com.codingapi.springboot.fast.jpa.map.QueryColumns; import com.codingapi.springboot.fast.jpa.map.QueryColumnsContext; +import com.codingapi.springboot.fast.jpa.map.QueryColumns; +import com.codingapi.springboot.fast.jpa.map.MapViewResult; import lombok.AllArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -17,12 +17,12 @@ public class JPAQuery { private final EntityManager entityManager; - public List listQuery(SQLBuilder builder) { + public List listQuery(SQLBuilder builder) { return listQuery(builder.getClazz(),builder.getSQL(),builder.getParams()); } - public List listQuery(Class clazz, String sql, Object... params) { - TypedQuery query = entityManager.createQuery(sql, clazz); + public List listQuery(Class clazz, String sql, Object... params) { + TypedQuery query = entityManager.createQuery(sql, clazz); if (params != null) { for (int i = 0; i < params.length; i++) { query.setParameter(i + 1, params[i]); @@ -31,17 +31,17 @@ public List listQuery(Class clazz, String sql, Object... params) { return query.getResultList(); } - public Page pageQuery(SQLBuilder builder,PageRequest pageRequest) { + public Page pageQuery(SQLBuilder builder,PageRequest pageRequest) { return pageQuery(builder.getClazz(), builder.getSQL(), builder.getCountSQL(),pageRequest,builder.getParams()); } - public Page pageQuery(Class clazz, String sql, PageRequest pageRequest, Object... params) { - return pageQuery(clazz,sql,"select count(1) " + sql,pageRequest,params); + public Page pageQuery(Class clazz, String sql, PageRequest pageRequest, Object... params) { + return pageQuery(clazz,sql,"SELECT COUNT(1) " + sql,pageRequest,params); } - public Page pageQuery(Class clazz, String sql, String countSql, PageRequest pageRequest, Object... params) { - TypedQuery query = entityManager.createQuery(sql, clazz); + public Page pageQuery(Class clazz, String sql, String countSql, PageRequest pageRequest, Object... params) { + TypedQuery query = entityManager.createQuery(sql, clazz); if (params != null) { for (int i = 0; i < params.length; i++) { query.setParameter(i + 1, params[i]); @@ -49,7 +49,7 @@ public Page pageQuery(Class clazz, String sql, String countSql, PageReques } query.setFirstResult(pageRequest.getPageNumber() * pageRequest.getPageSize()); query.setMaxResults(pageRequest.getPageSize()); - return new PageImpl<>(query.getResultList(), pageRequest, countQuery(countSql, params)); + return new PageImpl(query.getResultList(), pageRequest, countQuery(countSql, params)); } @@ -64,18 +64,17 @@ private long countQuery(String sql, Object... params) { } public Page pageMapQuery(QueryColumns columns, String sql, String countSql, PageRequest pageRequest, Object... params) { - String querySql = "select new com.codingapi.springboot.fast.jpa.map.MapViewResult('"+columns.getKey()+"',"+ String.join(",", columns.getColumnSql()) + ") " + sql; - String countQuerySql = "select count(1) " + countSql; - Page result = (Page) pageQuery(MapViewResult.class,querySql,countQuerySql,pageRequest,params); + String querySql = "SELECT new com.codingapi.springboot.fast.jpa.map.MapViewResult('"+columns.getKey()+"',"+ String.join(",", columns.getColumnSql()) + ") " + sql; + String countQuerySql = "SELECT COUNT(1) " + countSql; + Page result = pageQuery(MapViewResult.class,querySql,countQuerySql,pageRequest,params); QueryColumnsContext.getInstance().clearCache(columns.getKey()); return result; } - public List listMapQuery(QueryColumns columns, String sql, Object... params) { - String querySql = "select new com.codingapi.springboot.fast.jpa.map.MapViewResult('"+columns.getKey()+"',"+ String.join(",", columns.getColumnSql()) + ") " + sql; - List result = listQuery(MapViewResult.class,querySql,params); + public List listMapQuery(QueryColumns columns, String sql, Object... params) { + String querySql = "SELECT new com.codingapi.springboot.fast.jpa.map.MapViewResult('"+columns.getKey()+"',"+ String.join(",", columns.getColumnSql()) + ") " + sql; + List result = listQuery(MapViewResult.class,querySql,params); QueryColumnsContext.getInstance().clearCache(columns.getKey()); return result; } - } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java index 8f6bec96..2639d614 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java @@ -5,39 +5,44 @@ import java.util.ArrayList; import java.util.List; -public class SQLBuilder { +public class SQLBuilder { - private final StringBuilder sqlBuilder; + private final StringBuilder querySqlBuilder; private final StringBuilder countSQLBuilder; @Getter private int index; private final List params; @Getter - private final Class clazz; + private final Class clazz; public SQLBuilder(String sql) { this(null, sql, "select count(1) from " + sql); } - public SQLBuilder(Class clazz, String sql) { - this(clazz, sql, "select count(1) from " + sql); - } - public SQLBuilder(String sql,String countSql) { this(null, sql, countSql); } - public SQLBuilder(Class clazz, String sql, String countSQL) { + public SQLBuilder(Class clazz, String sql) { + this(clazz, sql, "select count(1) from " + sql); + } + + public SQLBuilder(Class clazz, String sql, String countSQL) { this.countSQLBuilder = new StringBuilder(countSQL); - this.sqlBuilder = new StringBuilder(sql); + this.querySqlBuilder = new StringBuilder(sql); this.index = 1; this.params = new ArrayList<>(); this.clazz = clazz; } + /** + * Append SQL condition with a value.sql end value must be a placeholder (e.g., "?"). + * @param sql the SQL condition to append, e.g., "where id = ?" + * @param value the value to bind to the SQL condition + */ public void append(String sql, Object value) { if (value != null) { - sqlBuilder.append(" ").append(sql).append(index).append(" "); + querySqlBuilder.append(" ").append(sql).append(index).append(" "); countSQLBuilder.append(" ").append(sql).append(index).append(" "); params.add(value); index++; @@ -55,12 +60,12 @@ public void addParam(Object value,int index){ } public void appendSql(String sql){ - sqlBuilder.append(" ").append(sql).append(" "); + querySqlBuilder.append(" ").append(sql).append(" "); countSQLBuilder.append(" ").append(sql).append(" "); } public String getSQL() { - return sqlBuilder.toString(); + return querySqlBuilder.toString(); } public String getCountSQL() { diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java index 7641a488..3adf3854 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java @@ -12,7 +12,7 @@ @NoRepositoryBean public interface DynamicNativeRepository extends BaseRepository { - default List> dynamicNativeListMapQuery(SQLBuilder builder) { + default List> dynamicNativeListMapQuery(SQLBuilder builder) { return JdbcQueryContext.getInstance().getJdbcQuery().queryForMapList(builder); } @@ -28,7 +28,7 @@ default List dynamicNativeListQuery(Class clazz, String sql, Object... return JdbcQueryContext.getInstance().getJdbcQuery().queryForList(sql, clazz, params); } - default List dynamicNativeListQuery(SQLBuilder sqlBuilder) { + default List dynamicNativeListQuery(SQLBuilder sqlBuilder) { return JdbcQueryContext.getInstance().getJdbcQuery().queryForList(sqlBuilder); } @@ -48,11 +48,11 @@ default Page dynamicNativePageQuery(Class clazz, String sql, PageReque return JdbcQueryContext.getInstance().getJdbcQuery().queryForPage(sql, clazz, request, params); } - default Page dynamicNativePageQuery(SQLBuilder sqlBuilder, PageRequest request) { + default Page dynamicNativePageQuery(SQLBuilder sqlBuilder, PageRequest request) { return JdbcQueryContext.getInstance().getJdbcQuery().queryForPage(sqlBuilder, request); } - default Page> dynamicNativeMapPageMapQuery(SQLBuilder sqlBuilder,PageRequest request) { + default Page> dynamicNativeMapPageMapQuery(SQLBuilder sqlBuilder,PageRequest request) { return JdbcQueryContext.getInstance().getJdbcQuery().queryForMapPage(sqlBuilder,request); } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java index ae675698..a18667e4 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java @@ -11,43 +11,42 @@ import java.util.List; @NoRepositoryBean -@SuppressWarnings("unchecked") public interface DynamicRepository extends BaseRepository { - default List dynamicListQuery(SQLBuilder builder) { - return (List) JpaQueryContext.getInstance().getJPAQuery().listQuery(builder); + default List dynamicListQuery(SQLBuilder builder) { + return JpaQueryContext.getInstance().getJPAQuery().listQuery(builder); } default List dynamicListQuery(String sql, Object... params) { - return (List) JpaQueryContext.getInstance().getJPAQuery().listQuery(getEntityClass(), sql, params); + return JpaQueryContext.getInstance().getJPAQuery().listQuery(getEntityClass(), sql, params); } default List dynamicListQuery(Class clazz, String sql, Object... params) { - return (List) JpaQueryContext.getInstance().getJPAQuery().listQuery(clazz, sql, params); + return JpaQueryContext.getInstance().getJPAQuery().listQuery(clazz, sql, params); } - default Page dynamicPageQuery(SQLBuilder builder, PageRequest request) { - return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(builder, request); + default Page dynamicPageQuery(SQLBuilder builder, PageRequest request) { + return JpaQueryContext.getInstance().getJPAQuery().pageQuery(builder, request); } default Page dynamicPageQuery(String sql, String countSql, PageRequest request, Object... params) { - return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, countSql, request, params); + return JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, countSql, request, params); } default Page dynamicPageQuery(String sql, PageRequest request, Object... params) { - return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, request, params); + return JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, request, params); } default Page dynamicPageQuery(Class clazz, String sql, String countSql, PageRequest request, Object... params) { - return (Page) JpaQueryContext.getInstance().getJPAQuery().pageQuery(clazz, sql, countSql, request, params); + return JpaQueryContext.getInstance().getJPAQuery().pageQuery(clazz, sql, countSql, request, params); } default Page dynamicMapPageQuery(QueryColumns columns, String sql, String countSql, PageRequest request, Object... params) { return JpaQueryContext.getInstance().getJPAQuery().pageMapQuery(columns, sql, countSql, request, params); } - default List dynamicMapListQuery(QueryColumns columns, String sql, Object... params) { - return (List) JpaQueryContext.getInstance().getJPAQuery().listMapQuery(columns, sql, params); + default List dynamicMapListQuery(QueryColumns columns, String sql, Object... params) { + return JpaQueryContext.getInstance().getJPAQuery().listMapQuery(columns, sql, params); } } diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index b8026c82..dff7a217 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.9 + 2.10.10 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index f5db5a94..4f66f1b8 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.9 + 2.10.10 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index bb058929..59178725 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.9 + 2.10.10 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 16d4b943..a9a8332a 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.9 +CodingApi SpringBoot-Starter 2.10.10 springboot version (${spring-boot.version}) ------------------------------------------------------ From d78830d7401314aeee33ab0fc6efcc6f8b895c0c Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 17 Jul 2025 20:58:18 +0800 Subject: [PATCH 109/129] fix flow bug --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../flow/service/FlowDirectionService.java | 27 +- .../flow/service/FlowNodeService.java | 22 -- .../flow/service/impl/FlowSubmitService.java | 6 +- .../springboot/flow/test/FlowRejectTest.java | 242 ++++++++++++++++++ .../springboot/flow/test/FlowRemoveTest.java | 213 +++++++++++++++ .../flow/test/MultiRelationFlowTest.java | 22 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 13 files changed, 470 insertions(+), 76 deletions(-) create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRejectTest.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRemoveTest.java diff --git a/pom.xml b/pom.xml index 824344fd..e28b6689 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.10 + 2.10.11 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 0c146ba7..775df41e 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.10 + 2.10.11 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 8901560b..9def015f 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.10 + 2.10.11 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index dff7a217..5da5e6ca 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.10 + 2.10.11 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java index 367efa68..5ed0216c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java @@ -48,6 +48,7 @@ public void loadFlowSourceDirection() { } } + /** * 重新加载审批方向 * 根据会签结果判断是否需要重新设置审批方向 @@ -84,26 +85,6 @@ public boolean hasCurrentFlowNodeIsDone() { return historyRecords.stream().filter(item -> !item.isTransfer()).allMatch(FlowRecord::isDone); } - - /** - * 检测当前流程是否已经完成 - * 即流程已经进行到了最终节点且审批意见为同意 - */ - public boolean hasCurrentFlowIsFinish() { - if (flowSourceDirection == FlowSourceDirection.PASS && flowNode.isOverNode()) { - return true; - } - return false; - } - - - /** - * 判断当前流程是否为默认的驳回流程 - */ - public boolean isDefaultBackRecord() { - return flowSourceDirection == FlowSourceDirection.REJECT && !flowWork.hasBackRelation(); - } - /** * 判断当前流程是否为通过流程 */ @@ -111,11 +92,5 @@ public boolean isPassRecord() { return flowSourceDirection == FlowSourceDirection.PASS; } - /** - * 判断当前流程是否为自定义的驳回流程 - */ - public boolean isCustomBackRecord() { - return flowSourceDirection == FlowSourceDirection.REJECT && flowWork.hasBackRelation(); - } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java index 96f5258c..e3b0178e 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java @@ -146,28 +146,6 @@ public void loadDefaultBackNode(FlowRecord currentRecord) { } - /** - * 加载自定义回退节点 - */ - public void loadCustomBackNode(FlowNode flowNode, long parentRecordId) { - FlowNode nextNode = this.matcherNextNode(flowNode, true); - if (nextNode == null) { - throw new IllegalArgumentException("next node not found"); - } - IFlowOperator flowOperator = currentOperator; - if (nextNode.isAnyOperatorMatcher()) { - // 如果是任意人员操作时则需要指定为当时审批人员为当前审批人员 - FlowRecord preFlowRecord = flowRecordRepository.getFlowRecordById(parentRecordId); - while (preFlowRecord.isTransfer() || !preFlowRecord.getNodeCode().equals(nextNode.getCode())) { - preFlowRecord = flowRecordRepository.getFlowRecordById(preFlowRecord.getPreId()); - } - flowOperator = preFlowRecord.getCurrentOperator(); - } - this.nextNode = nextNode; - this.nextOperator = flowOperator; - this.backOperator = null; - } - /** * 获取下一个节点 diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index 30115350..887f0553 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -192,12 +192,8 @@ private void loadNextNode(List historyRecords) { // 审批通过并进入下一节点 if (flowDirectionService.isPassRecord()) { flowNodeService.loadNextPassNode(flowNode); - // 审批拒绝返回上一节点 - } else if (flowDirectionService.isDefaultBackRecord()) { + } else { flowNodeService.loadDefaultBackNode(flowRecord); - } else { - // 审批拒绝,并且自定了返回节点 - flowNodeService.loadCustomBackNode(flowNode, flowRecord.getPreId()); } this.nextNode = flowNodeService.getNextNode(); } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRejectTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRejectTest.java new file mode 100644 index 00000000..614f55a3 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRejectTest.java @@ -0,0 +1,242 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.pojo.FlowResult; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.trigger.OutTrigger; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class FlowRejectTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository, userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository, flowProcessRepository, flowBackupRepository); + + /** + * 驳回测试 + */ + @Test + void reject1() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),lorne.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("总经理审批", "dept", "start",new OutTrigger(" def run(content) {\n" + + " return false;\n" + + " }"),1,true) + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(lorne.getUserId())); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + List lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + // 提交委托lorne部门经理的审批 + FlowRecord lorneTodo = lorneTodos.get(0); + flowService.submitFlow(lorneTodo.getId(), lorne, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + FlowResult flowResult = flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.reject("不同意")); + System.out.println(flowResult.getRecords()); + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + lorneTodo = lorneTodos.get(0); + flowService.submitFlow(lorneTodo.getId(), lorne, leave, Opinion.pass("同意")); + + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(6, snapshots.size()); + + } + + + + /** + * 驳回测试 + */ + @Test + void reject2() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),lorne.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(lorne.getUserId())); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + List lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + // 提交委托lorne部门经理的审批 + FlowRecord lorneTodo = lorneTodos.get(0); + flowService.submitFlow(lorneTodo.getId(), lorne, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + FlowResult flowResult = flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.reject("不同意")); + System.out.println(flowResult.getRecords()); + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + lorneTodo = lorneTodos.get(0); + flowService.submitFlow(lorneTodo.getId(), lorne, leave, Opinion.pass("同意")); + + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(6, snapshots.size()); + + } + +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRemoveTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRemoveTest.java new file mode 100644 index 00000000..902fe89c --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRemoveTest.java @@ -0,0 +1,213 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class FlowRemoveTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository, userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository, flowProcessRepository, flowBackupRepository); + + /** + * 删除流程测试 (在未提交之前删除流程) + */ + @Test + void removeTest1() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + // 保存流程 + leave.setTitle("我要出去看看~~"); + flowService.remove(userTodo.getId(), user); + + List records = flowRecordRepository.findFlowRecordByProcessId(userTodo.getProcessId()); + assertEquals(0, records.size()); + + } + + /** + * 删除流程测试 (提交以后删除异常) + */ + @Test + void removeTest2() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user,leave, Opinion.pass("同意")); + + + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + FlowRecord deptTodo = deptTodos.get(0); + assertThrows(Exception.class, () -> { + flowService.remove(deptTodo.getId(), dept); + }); + + List records = flowRecordRepository.findFlowRecordByProcessId(userTodo.getProcessId()); + assertEquals(2, records.size()); + + } + + + /** + * 删除流程测试 (提交以后再撤回然后继续删除) + */ + @Test + void removeTest3() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user,leave, Opinion.pass("同意")); + + + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + FlowRecord deptTod = deptTodos.get(0); + flowService.submitFlow(deptTod.getId(), dept,leave, Opinion.reject("不同意")); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.remove(userTodo.getId(), user); + + List records = flowRecordRepository.findFlowRecordByProcessId(userTodo.getProcessId()); + assertEquals(0, records.size()); + + } +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java index dea70b23..9dc4a223 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java @@ -199,6 +199,7 @@ void relationTest2(){ + /** * 多条件流程测试撤回 */ @@ -272,33 +273,22 @@ void relationTest3(){ assertEquals(4, records.size()); // 用户修改确认 - userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); // 用户调整为3天 leave.setDays(3); // 提交流程 - userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); - - records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(5, records.size()); - - deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); - assertEquals(1, deptTodos.size()); - - // 提交部门经理的审批 deptTodo = deptTodos.get(0); flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); - // 用户修改确认 - userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(0, userTodos.size()); + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); // 查看所有流程是否都已经结束 assertTrue(records.stream().allMatch(FlowRecord::isFinish)); List snapshots = flowBindDataRepository.findAll(); - assertEquals(6, snapshots.size()); + assertEquals(5, snapshots.size()); } } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 4f66f1b8..8a2f36a3 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.10 + 2.10.11 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 59178725..83edb797 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.10 + 2.10.11 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index a9a8332a..3577a99a 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.10 +CodingApi SpringBoot-Starter 2.10.11 springboot version (${spring-boot.version}) ------------------------------------------------------ From 68771814c66d3207756ff85c22e311e17910f198 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 25 Jul 2025 14:32:17 +0800 Subject: [PATCH 110/129] fix ossrh pom --- pom.xml | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/pom.xml b/pom.xml index e28b6689..33eb9dd0 100644 --- a/pom.xml +++ b/pom.xml @@ -352,18 +352,6 @@ - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${maven.compile.source} - ${maven.compile.target} - ${project.build.sourceEncoding} - -Xlint:deprecation - - org.apache.maven.plugins maven-source-plugin @@ -377,19 +365,6 @@ - - - - - - - - - - - - - org.sonatype.central central-publishing-maven-plugin @@ -420,7 +395,6 @@ - org.apache.maven.plugins maven-gpg-plugin @@ -439,8 +413,6 @@ - - From 4e7ca69a8469fc17f09ebb1a282339f3641c191f Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 28 Jul 2025 20:42:10 +0800 Subject: [PATCH 111/129] fix flow bug --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/domain/FlowWork.java | 6 +- .../flow/service/FlowNodeService.java | 24 +- .../flow/service/impl/FlowSubmitService.java | 2 +- .../springboot/flow/test/FlowRejectTest.java | 216 ++++++++++++++++++ .../flow/test/MultiRelationFlowTest.java | 93 -------- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 12 files changed, 251 insertions(+), 104 deletions(-) diff --git a/pom.xml b/pom.xml index 33eb9dd0..31073930 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.11 + 2.10.12 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 775df41e..14cc4205 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.11 + 2.10.12 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 9def015f..bb421262 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.11 + 2.10.12 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 5da5e6ca..1cc5eb67 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.11 + 2.10.12 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java index b6ad791a..05a6ca3c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java @@ -309,8 +309,10 @@ public FlowNode getStartNode() { /** * 是否存在退回关系 */ - public boolean hasBackRelation() { - return relations.stream().anyMatch(FlowRelation::isBack); + public boolean hasBackRelation(String sourceCode) { + return relations.stream() + .filter(relation -> relation.getSource().getCode().equals(sourceCode)) + .anyMatch(FlowRelation::isBack); } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java index e3b0178e..facb0e47 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java @@ -102,7 +102,29 @@ public void skipCirculate() { /** * 加载默认回退节点 */ - public void loadDefaultBackNode(FlowRecord currentRecord) { + public void loadDefaultBackNode(FlowNode flowNode,FlowRecord currentRecord) { + // 如果退回设置了回退关系,则需要根据关系匹配下一个节点 + if (flowWork.hasBackRelation(flowNode.getCode())) { + FlowNode nextNode = this.matcherNextNode(flowNode, true); + if (nextNode == null) { + throw new IllegalArgumentException("next node not found"); + } + long parentRecordId = currentRecord.getPreId(); + FlowRecord preFlowRecord = flowRecordRepository.getFlowRecordById(parentRecordId); + IFlowOperator flowOperator = currentOperator; + if (nextNode.isAnyOperatorMatcher()) { + while (preFlowRecord.isTransfer() || !preFlowRecord.getNodeCode().equals(nextNode.getCode())) { + preFlowRecord = flowRecordRepository.getFlowRecordById(preFlowRecord.getPreId()); + } + flowOperator = preFlowRecord.getCurrentOperator(); + } + this.nextNode = nextNode; + this.nextOperator = flowOperator; + this.backOperator = null; + return; + } + + // 如果没有设置回退关系,则需要根据流程记录来匹配下一个节点 List historyRecords = flowRecordRepository.findFlowRecordByProcessId(currentRecord.getProcessId()) .stream() diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java index 887f0553..9b2eecc3 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -193,7 +193,7 @@ private void loadNextNode(List historyRecords) { if (flowDirectionService.isPassRecord()) { flowNodeService.loadNextPassNode(flowNode); } else { - flowNodeService.loadDefaultBackNode(flowRecord); + flowNodeService.loadDefaultBackNode(flowNode,flowRecord); } this.nextNode = flowNodeService.getNextNode(); } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRejectTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRejectTest.java index 614f55a3..bd63f867 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRejectTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRejectTest.java @@ -239,4 +239,220 @@ void reject2() { } + + + /** + * 驳回测试3 + */ + @Test + void reject3() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("总经理审批", "manager", "start",new OutTrigger("" + + "def run(content) {\n" + + " if(content.getBindData().getDays() > 3) {\n" + + " return true;\n" + + " }\n" + + " return false;\n" + + " }"),1,true) + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leave.setDays(5); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(dept.getUserId())); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 部门经理的提交审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.reject("不同意")); + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + userTodo = userTodos.get(0); + leave.setDays(3); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 部门经理的提交审批 + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交总经理的审批 + bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(6, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(7, snapshots.size()); + + } + + + + /** + * 多条件流程测试撤回 + */ + @Test + void reject4(){ + PageRequest pageRequest = PageRequest.of(0, 1000); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "over",new OutTrigger("def run(content){content.getBindData().getDays()<=5}"),1,false) + .relation("总经理审批", "dept", "manager",new OutTrigger("def run(content){content.getBindData().getDays()>5}"),2,false) + .relation("结束节点", "manager", "start",new OutTrigger("def run(content){return true}"),1,true) + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看",6); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + // 查看部门经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + FlowRecord deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + + // 查看老板的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交老板的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.reject("不同意,最多让你请假3天")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(4, records.size()); + + // 用户修改确认 + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 用户调整为3天 + leave.setDays(3); + // 提交流程 + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); + + deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(1, deptTodos.size()); + + // 提交部门经理的审批 + deptTodo = deptTodos.get(0); + flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(6, snapshots.size()); + } + } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java index 9dc4a223..485286c9 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java @@ -198,97 +198,4 @@ void relationTest2(){ } - - - /** - * 多条件流程测试撤回 - */ - @Test - void relationTest3(){ - - PageRequest pageRequest = PageRequest.of(0, 1000); - - User user = new User("张飞"); - userRepository.save(user); - - User dept = new User("刘备"); - userRepository.save(dept); - - User boss = new User("诸葛亮"); - userRepository.save(boss); - - - FlowWork flowWork = FlowWorkBuilder.builder(user) - .title("请假流程") - .nodes() - .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) - .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId())) - .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) - .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) - .relations() - .relation("部门领导审批", "start", "dept") - .relation("总经理审批", "dept", "over",new OutTrigger("def run(content){content.getBindData().getDays()<=5}"),1,false) - .relation("总经理审批", "dept", "manager",new OutTrigger("def run(content){content.getBindData().getDays()>5}"),2,false) - .relation("结束节点", "manager", "start",new OutTrigger("def run(content){return true}"),1,true) - .relation("结束节点", "manager", "over") - .build(); - - flowWorkRepository.save(flowWork); - - String workCode = flowWork.getCode(); - - Leave leave = new Leave("我要出去看看",6); - leaveRepository.save(leave); - - // 创建流程 - flowService.startFlow(workCode, user, leave, "发起流程"); - - // 查看我的待办 - List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); - assertEquals(1, userTodos.size()); - - // 提交流程 - FlowRecord userTodo = userTodos.get(0); - flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意")); - - // 查看部门经理的待办 - List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); - assertEquals(1, deptTodos.size()); - - // 提交部门经理的审批 - FlowRecord deptTodo = deptTodos.get(0); - flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); - - - // 查看老板的待办 - List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); - assertEquals(1, bossTodos.size()); - - // 提交老板的审批 - FlowRecord bossTodo = bossTodos.get(0); - flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.reject("不同意,最多让你请假3天")); - - // 查看所有流程 - List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); - - // 用户修改确认 - deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); - assertEquals(1, deptTodos.size()); - - // 用户调整为3天 - leave.setDays(3); - // 提交流程 - deptTodo = deptTodos.get(0); - flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意")); - - records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(4, records.size()); - - // 查看所有流程是否都已经结束 - assertTrue(records.stream().allMatch(FlowRecord::isFinish)); - - List snapshots = flowBindDataRepository.findAll(); - assertEquals(5, snapshots.size()); - } } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 8a2f36a3..69fd30d5 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.11 + 2.10.12 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 83edb797..f47cab80 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.11 + 2.10.12 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 3577a99a..19cc62bc 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.11 +CodingApi SpringBoot-Starter 2.10.12 springboot version (${spring-boot.version}) ------------------------------------------------------ From 949ecbd9c0acc761b2a5690f194abdf0f0cff517 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 22 Aug 2025 08:50:47 +0800 Subject: [PATCH 112/129] fix 2.10.13 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/record/FlowRecord.java | 9 + .../flow/service/FlowRecordVerifyService.java | 8 + .../flow/service/impl/FlowRecallService.java | 35 +-- .../springboot/flow/test/FlowRecallTest.java | 236 ++++++++++++++++++ .../springboot/flow/test/FlowTest.java | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 12 files changed, 279 insertions(+), 25 deletions(-) create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRecallTest.java diff --git a/pom.xml b/pom.xml index 31073930..1bb408b0 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.12 + 2.10.13 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 14cc4205..d6cecc20 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.12 + 2.10.13 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index bb421262..9b7bdb7d 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.12 + 2.10.13 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 1cc5eb67..cbf2423d 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.12 + 2.10.13 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java index 75c54ceb..c3735dc0 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -376,6 +376,15 @@ public void matcherOperator(IFlowOperator currentOperator) { } } + /** + * 是否是当前发起人 + * @param operator 操作者 + * @return 是否是当前发起人 + */ + public boolean isCreateOperator(IFlowOperator operator) { + return this.createOperator.getUserId() == operator.getUserId(); + } + /** * 是否是当前操作者 * diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java index 003db90c..01ecf875 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java @@ -83,6 +83,14 @@ public void verifyFlowRecordCurrentOperator() { } } + /** + * 当前人是否为发起人 + * @return 是否为发起人 + */ + public boolean isCreateOperator() { + return flowRecord.isCreateOperator(currentOperator); + } + /** * 校验流程是否已审批 */ diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java index ba6849ee..e831f86f 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java @@ -38,7 +38,8 @@ public void recall(long recordId, IFlowOperator currentOperator) { flowWorkRepository, flowRecordRepository, flowProcessRepository, - recordId, currentOperator); + recordId, + currentOperator); flowRecordVerifyService.verifyFlowRecordCurrentOperator(); flowRecordVerifyService.loadFlowWork(); @@ -48,23 +49,23 @@ public void recall(long recordId, IFlowOperator currentOperator) { FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); FlowWork flowWork = flowRecordVerifyService.getFlowWork(); - - // 下一流程的流程记录 - List childrenRecords = flowRecordRepository.findFlowRecordByPreId(recordId); - BindDataSnapshot bindDataSnapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); - // 下一流程均为办理且未读 - - // 如果是在开始节点撤销,则直接删除 - if (flowRecord.isStartRecord() && flowRecord.isTodo()) { - if (!childrenRecords.isEmpty()) { - throw new IllegalArgumentException("flow record not recall"); + if(flowRecordVerifyService.isCreateOperator()){ + List records = flowRecordRepository.findFlowRecordByProcessId(flowRecord.getProcessId()); + for(FlowRecord record:records){ + if(!record.isStartRecord()) { + record.delete(); + flowRecordRepository.update(record); + }else { + record.recall(); + flowRecordRepository.update(record); + } } - List flowRecords = new ArrayList<>(); - flowRecords.add(flowRecord); - flowRecordRepository.delete(flowRecords); - } else { + }else { + // 下一流程的流程记录 + List childrenRecords = flowRecordRepository.findFlowRecordByPreId(recordId); + // 如果是在中间节点撤销,则需要判断是否所有的子流程都是未读状态 if (childrenRecords.isEmpty()) { throw new IllegalArgumentException("flow record not submit"); @@ -77,13 +78,13 @@ public void recall(long recordId, IFlowOperator currentOperator) { flowRecord.recall(); flowRecordRepository.update(flowRecord); - for(FlowRecord childrenRecord : childrenRecords) { + for (FlowRecord childrenRecord : childrenRecords) { childrenRecord.delete(); } flowRecordRepository.save(childrenRecords); } - IBindData bindData = bindDataSnapshot.toBindData(); + IBindData bindData = bindDataSnapshot.toBindData(); EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_RECALL, flowRecord, currentOperator, flowWork, bindData), true); } } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRecallTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRecallTest.java new file mode 100644 index 00000000..ddeb67b9 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRecallTest.java @@ -0,0 +1,236 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class FlowRecallTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository, userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository, flowProcessRepository, flowBackupRepository); + + /** + * 撤回测试(发起人撤销测试) + */ + @Test + void recall1() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),lorne.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(lorne.getUserId())); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + List lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + // 提交委托lorne部门经理的审批 + FlowRecord lorneTodo = lorneTodos.get(0); + flowService.submitFlow(lorneTodo.getId(), lorne, leave, Opinion.pass("同意")); + + List userDones = flowRecordRepository.findDoneByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userDones.size()); + + FlowRecord userDone = userDones.get(0); + flowService.recall(userDone.getId(),user); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(lorne.getUserId())); + + lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + lorneTodo = lorneTodos.get(0); + flowService.submitFlow(lorneTodo.getId(), lorne, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交委托lorne部门经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(6, snapshots.size()); + + } + + + /** + * 撤回测试(流程已读) + */ + @Test + void recall2() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),lorne.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(lorne.getUserId())); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + List lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + // 提交委托lorne部门经理的审批 + FlowRecord lorneTodo = lorneTodos.get(0); + flowService.submitFlow(lorneTodo.getId(), lorne, leave, Opinion.pass("同意")); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + // 提交委托boos部门经理的审批 + FlowRecord bossTodo = bossTodos.get(0); + flowService.detail(bossTodo.getId()); + flowService.save(bossTodo.getId(), boss, leave, "..."); + + List lorneDones = flowRecordRepository.findDoneByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneDones.size()); + + FlowRecord lorneDone = lorneDones.get(0); + flowService.recall(lorneDone.getId(),lorne); + + lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + lorneTodo = lorneTodos.get(0); + flowService.submitFlow(lorneTodo.getId(), lorne, leave, Opinion.pass("同意")); + + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + bossTodo = bossTodos.get(0); + flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意")); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(3, records.size()); + + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(5, snapshots.size()); + + } + +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java index de27d23c..1557436f 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java @@ -1103,7 +1103,7 @@ void recallTest2() { flowService.recall(userTodo.getId(), user); List records = flowRecordRepository.findAll(pageRequest).getContent(); - assertEquals(0, records.size()); + assertEquals(1, records.size()); } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 69fd30d5..da67d10c 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.12 + 2.10.13 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index f47cab80..a3256f8a 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.12 + 2.10.13 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 19cc62bc..2b0c9603 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.12 +CodingApi SpringBoot-Starter 2.10.13 springboot version (${spring-boot.version}) ------------------------------------------------------ From 59bece773c13ef45cdf36bc1c161c03121e6de09 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 27 Aug 2025 16:56:00 +0800 Subject: [PATCH 113/129] fix #144 --- event.md | 2 + pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/domain/Opinion.java | 8 +- .../flow/event/FlowApprovalEvent.java | 2 + .../springboot/flow/record/FlowRecord.java | 11 ++ .../springboot/flow/service/FlowService.java | 11 ++ .../flow/service/impl/FlowStopService.java | 102 ++++++++++ .../springboot/flow/test/FlowStopTest.java | 187 ++++++++++++++++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 14 files changed, 329 insertions(+), 8 deletions(-) create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStopService.java create mode 100644 springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowStopTest.java diff --git a/event.md b/event.md index 1456cd02..d632f4a7 100644 --- a/event.md +++ b/event.md @@ -26,6 +26,8 @@ 事件: URGE 当前审批人 * 延期流程 事件: 未发送事件 +* 停止流程 +事件: STOP 当前审批人 --------------------- 自定义事件:是前端自己触法的逻辑 diff --git a/pom.xml b/pom.xml index 1bb408b0..edf29ecf 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.13 + 2.10.14 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index d6cecc20..057b1525 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.13 + 2.10.14 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 9b7bdb7d..58e5be81 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.13 + 2.10.14 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index cbf2423d..8ce25dee 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.13 + 2.10.14 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java index f9f72e78..62b73d17 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java @@ -35,6 +35,8 @@ public class Opinion { public static final int RESULT_CIRCULATE = 4; // 审批结果 等待 public static final int RESULT_WAITING = 5; + // 审批结果 停止 + public static final int RESULT_STOP = 6; /** @@ -83,6 +85,10 @@ public static Opinion pass(String advice) { return new Opinion(advice, RESULT_PASS, TYPE_DEFAULT); } + public static Opinion stop() { + return new Opinion("", RESULT_STOP, TYPE_DEFAULT); + } + public static Opinion reject(String advice) { return new Opinion(advice, RESULT_REJECT, TYPE_DEFAULT); } @@ -114,7 +120,7 @@ public boolean isSuccess() { public boolean isWaiting() { return result == RESULT_WAITING; } - + public boolean isReject() { return result == RESULT_REJECT; } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java index fb160551..4e6c465c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java @@ -42,6 +42,8 @@ public class FlowApprovalEvent implements ISyncEvent { public static final int STATE_BACK = 12; // 作废 public static final int STATE_VOIDED = 13; + // 停止 + public static final int STATE_STOP = 14; private final int state; diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java index c3735dc0..2da107d2 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -247,6 +247,17 @@ public void circulate() { this.opinion = Opinion.circulate(); } + + /** + * 停止流程 + */ + public void stop(){ + this.flowSourceDirection = FlowSourceDirection.PASS; + this.flowType = FlowType.DONE; + this.updateTime = System.currentTimeMillis(); + this.opinion = Opinion.stop(); + } + /** * 转交流程 */ diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index 103178c2..2fd1c117 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -314,4 +314,15 @@ public void voided(String processId, IFlowOperator currentOperator) { public void back(String processId, String backNodeCode, IFlowOperator currentOperator) { flowBackService.back(processId, backNodeCode, currentOperator); } + + /** + * 停止流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public void stop(long recordId, IFlowOperator currentOperator) { + FlowStopService flowSubmitService = new FlowStopService(recordId, currentOperator, flowServiceRepositoryHolder); + flowSubmitService.stop(); + } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStopService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStopService.java new file mode 100644 index 00000000..1c8a4bb8 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStopService.java @@ -0,0 +1,102 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.domain.FlowNode; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.event.FlowApprovalEvent; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.FlowBindDataRepository; +import com.codingapi.springboot.flow.repository.FlowRecordRepository; +import com.codingapi.springboot.flow.service.FlowRecordVerifyService; +import com.codingapi.springboot.flow.service.FlowServiceRepositoryHolder; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Transactional +public class FlowStopService { + + + private final IFlowOperator currentOperator; + private final FlowRecordVerifyService flowRecordVerifyService; + private final FlowRecordRepository flowRecordRepository; + private final FlowBindDataRepository flowBindDataRepository ; + + private FlowRecord flowRecord; + private FlowWork flowWork; + private FlowNode flowNode; + private BindDataSnapshot snapshot; + + + + public FlowStopService(long recordId, + IFlowOperator currentOperator, + FlowServiceRepositoryHolder flowServiceRepositoryHolder) { + this.currentOperator = currentOperator; + this.flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + this.flowBindDataRepository = flowServiceRepositoryHolder.getFlowBindDataRepository(); + this.flowRecordVerifyService = new FlowRecordVerifyService( + flowServiceRepositoryHolder.getFlowWorkRepository(), + flowServiceRepositoryHolder.getFlowRecordRepository(), + flowServiceRepositoryHolder.getFlowProcessRepository(), + recordId, + currentOperator); + } + + + // 加载流程 + private void loadFlow() { + // 验证流程的提交状态 + flowRecordVerifyService.verifyFlowRecordSubmitState(); + // 验证当前操作者 + flowRecordVerifyService.verifyFlowRecordCurrentOperator(); + + // 加载流程设计 + flowRecordVerifyService.loadFlowWork(); + // 加载流程节点 + flowRecordVerifyService.loadFlowNode(); + // 验证没有子流程 + flowRecordVerifyService.verifyChildrenRecordsIsEmpty(); + + this.flowRecord = flowRecordVerifyService.getFlowRecord(); + this.flowNode = flowRecordVerifyService.getFlowNode(); + this.flowWork = flowRecordVerifyService.getFlowWork(); + this.snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + } + + + + /** + * 提交流程 + **/ + public void stop() { + // 加载流程信息 + this.loadFlow(); + + // 停止流程 + flowRecord.stop(); + flowRecordRepository.update(flowRecord); + + List todoRecords = flowRecordRepository.findFlowRecordByProcessId(flowRecord.getProcessId()); + for (FlowRecord record : todoRecords) { + if (record.isTodo()) { + record.stop(); + flowRecordRepository.update(record); + } + } + + flowRecordRepository.finishFlowRecordByProcessId(flowRecord.getProcessId()); + + EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_STOP, + flowRecord, + flowRecord.getCurrentOperator(), + flowWork, + snapshot.toBindData() + ), true); + + } + + +} diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowStopTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowStopTest.java new file mode 100644 index 00000000..a312b222 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowStopTest.java @@ -0,0 +1,187 @@ +package com.codingapi.springboot.flow.test; + +import com.codingapi.springboot.flow.bind.BindDataSnapshot; +import com.codingapi.springboot.flow.build.FlowWorkBuilder; +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.em.ApprovalType; +import com.codingapi.springboot.flow.flow.Leave; +import com.codingapi.springboot.flow.matcher.OperatorMatcher; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.repository.*; +import com.codingapi.springboot.flow.service.FlowService; +import com.codingapi.springboot.flow.user.User; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * 流程停止测试 + */ +public class FlowStopTest { + + private final UserRepository userRepository = new UserRepository(); + private final FlowWorkRepository flowWorkRepository = new FlowWorkRepositoryImpl(); + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final FlowBindDataRepositoryImpl flowBindDataRepository = new FlowBindDataRepositoryImpl(); + private final LeaveRepository leaveRepository = new LeaveRepository(); + private final FlowBackupRepository flowBackupRepository = new FlowBackupRepositoryImpl(); + private final FlowProcessRepository flowProcessRepository = new FlowProcessRepositoryImpl(flowBackupRepository, userRepository); + private final FlowService flowService = new FlowService(flowWorkRepository, flowRecordRepository, flowBindDataRepository, userRepository, flowProcessRepository, flowBackupRepository); + + /** + * 流程提交以后停止 测试 + */ + @Test + void stop01() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),lorne.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(lorne.getUserId())); + + // 查看刘备经理的待办 + List deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent(); + assertEquals(0, deptTodos.size()); + + List lorneTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(1, lorneTodos.size()); + + // 提交委托lorne部门经理的审批 + FlowRecord lorneTodo = lorneTodos.get(0); + flowService.stop(lorneTodo.getId(), lorne); + + List userDones = flowRecordRepository.findDoneByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userDones.size()); + + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + // 查看总经理的待办 + List bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(0, bossTodos.size()); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(2, records.size()); + + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(2, snapshots.size()); + + } + + + /** + * 流程发起后直接停止 测试 + */ + @Test + void stop02() { + PageRequest pageRequest = PageRequest.of(0, 1000); + + User lorne = new User("lorne"); + userRepository.save(lorne); + + User user = new User("张飞"); + userRepository.save(user); + + User dept = new User("刘备"); + userRepository.save(dept); + + User boss = new User("诸葛亮"); + userRepository.save(boss); + + FlowWork flowWork = FlowWorkBuilder.builder(user) + .title("请假流程") + .nodes() + .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .node("部门领导审批", "dept", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId(),lorne.getUserId())) + .node("总经理审批", "manager", "default", ApprovalType.SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("结束节点", "manager", "over") + .build(); + + flowWorkRepository.save(flowWork); + + String workCode = flowWork.getCode(); + + Leave leave = new Leave("我要出去看看"); + leaveRepository.save(leave); + + // 创建流程 + flowService.startFlow(workCode, user, leave, "发起流程"); + + // 查看我的待办 + List userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + // 提交流程 + FlowRecord userTodo = userTodos.get(0); + assertEquals(0, userTodo.getTimeoutTime()); + + flowService.stop(userTodo.getId(), user); + + // 查看所有流程 + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(1, records.size()); + + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(1, snapshots.size()); + + } + +} diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index da67d10c..3928534c 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.13 + 2.10.14 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index a3256f8a..88732a5b 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.13 + 2.10.14 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 2b0c9603..3c7f60ab 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.13 +CodingApi SpringBoot-Starter 2.10.14 springboot version (${spring-boot.version}) ------------------------------------------------------ From 986bfe325e850b135ba88fbf52c0429da43993ab Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 1 Sep 2025 15:50:52 +0800 Subject: [PATCH 114/129] fix #144 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/content/FlowSession.java | 12 ++++++++++++ .../springboot/flow/event/FlowApprovalEvent.java | 4 ++++ springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 9 files changed, 23 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index edf29ecf..133351db 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.14 + 2.10.15 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 057b1525..923e4d41 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.14 + 2.10.15 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 58e5be81..0053cc24 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.14 + 2.10.15 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 8ce25dee..3dfa2877 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.14 + 2.10.15 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java index 60f94ae5..de4c7542 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java @@ -183,8 +183,20 @@ public MessageResult rejectFlow() { return MessageResult.create(result); } + /** + * 停止流程 + */ + public void stopFlow() { + if (flowRecord == null) { + throw new IllegalArgumentException("flow record is null"); + } + FlowService flowService = loadFlowService(); + flowService.stop(flowRecord.getId(), currentOperator); + } + /** * 上级节点的状态是驳回状态 + * * @return 上级节点的状态是驳回状态 */ public boolean backStateIsReject() { diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java index 4e6c465c..4f21d62e 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java @@ -89,6 +89,10 @@ public boolean isTodo() { return state == STATE_TODO; } + public boolean isStop() { + return state == STATE_STOP; + } + public boolean isSave() { return state == STATE_SAVE; } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 3928534c..3e2311c5 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.14 + 2.10.15 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 88732a5b..5699848a 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.14 + 2.10.15 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index 3c7f60ab..d2aa0439 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.14 +CodingApi SpringBoot-Starter 2.10.15 springboot version (${spring-boot.version}) ------------------------------------------------------ From bd1cc8d7e530a225c79f0e4717d55615c7175fef Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 1 Sep 2025 15:52:45 +0800 Subject: [PATCH 115/129] fix #144 --- .../springboot/fast/JdbcQueryTest.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/JdbcQueryTest.java diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/JdbcQueryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/JdbcQueryTest.java new file mode 100644 index 00000000..daa71d4a --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/JdbcQueryTest.java @@ -0,0 +1,44 @@ +package com.codingapi.springboot.fast; + +import com.codingapi.springboot.fast.entity.Demo; +import com.codingapi.springboot.fast.repository.DemoRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest +public class JdbcQueryTest { + + @Autowired + private DemoRepository demoRepository; + + + @Test + void test() { + demoRepository.deleteAll(); + Demo demo = new Demo(); + demo.setName("123"); + demoRepository.save(demo); + assertTrue(demo.getId() > 0); + + String sql = "select d.* from t_demo as d where d.id in (d.id,?,?)"; + String countSql = "select count(d.id) from t_demo as d where d.id in (d.id,?,?)"; + PageRequest pageRequest = PageRequest.of(0, 10); + + List params = Arrays.asList(demo.getId(), demo.getId()); + Page> page = demoRepository.dynamicNativeMapPageMapQuery( + sql, countSql, pageRequest, params.toArray() + ); + assertEquals(page.getTotalElements(), page.getContent().size()); + } + +} From f598b49fb6db3f4c086ce67785094b0b1fb68446 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 1 Sep 2025 18:22:24 +0800 Subject: [PATCH 116/129] fix recall record value --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- springboot-starter/src/main/resources/META-INF/banner.txt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 133351db..e991a6e2 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.15 + 2.10.16 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 923e4d41..0f4db9f6 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.15 + 2.10.16 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 0053cc24..4f818e0d 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.15 + 2.10.16 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 3dfa2877..90ff145a 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.15 + 2.10.16 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 3e2311c5..3fa1723e 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.15 + 2.10.16 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 5699848a..26f5fe05 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.15 + 2.10.16 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index d2aa0439..e43fe65a 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.15 +CodingApi SpringBoot-Starter 2.10.16 springboot version (${spring-boot.version}) ------------------------------------------------------ From 0810e1d896cfd5ec33c552c468460002818cdcfd Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 1 Sep 2025 18:23:31 +0800 Subject: [PATCH 117/129] fix recall record value --- .../springboot/flow/service/impl/FlowRecallService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java index e831f86f..ca52652c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java @@ -59,6 +59,7 @@ public void recall(long recordId, IFlowOperator currentOperator) { flowRecordRepository.update(record); }else { record.recall(); + flowRecord = record; flowRecordRepository.update(record); } } From 8f5c5be9433b49273b16a6443b0aab022bebc6ec Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 17 Sep 2025 14:49:17 +0800 Subject: [PATCH 118/129] update #152 #153 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../flow/service/impl/FlowStartService.java | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../framework/exception/EventException.java | 23 ++++++++++++++++--- 8 files changed, 27 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index e991a6e2..0056569b 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.16 + 2.10.17 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 0f4db9f6..5895ebb2 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.16 + 2.10.17 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 4f818e0d..8e419d6c 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.16 + 2.10.17 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 90ff145a..0bc93512 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.16 + 2.10.17 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java index d035a5e4..c8b8c127 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java @@ -66,7 +66,7 @@ private void loadFlowWork() { flowWork.enableValidate(); } - private void loadFlowBackup() { + private synchronized void loadFlowBackup() { FlowBackupRepository flowBackupRepository = flowServiceRepositoryHolder.getFlowBackupRepository(); this.flowBackup = flowBackupRepository.getFlowBackupByWorkIdAndVersion(flowWork.getId(), flowWork.getUpdateTime()); if (flowBackup == null) { diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 3fa1723e..bcf442e0 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.16 + 2.10.17 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 26f5fe05..710d2322 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.16 + 2.10.17 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java index 5a506fec..dec33086 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java @@ -3,7 +3,6 @@ import lombok.Getter; import java.util.List; -import java.util.stream.Collectors; @Getter public class EventException extends RuntimeException { @@ -11,10 +10,28 @@ public class EventException extends RuntimeException { private final List error; public EventException(List error) { - super(error.stream().map(Exception::getMessage).collect(Collectors.joining("\n"))); + super(EventException.convert(error)); this.error = error; for (Exception e : error) { - e.printStackTrace(); + this.addSuppressed(e); } } + + private static String convert(List errors){ + if (errors == null || errors.isEmpty()) { + return "No errors."; + } + StringBuilder message = new StringBuilder(); + message.append("Has ").append(errors.size()).append(" Errors:\n"); + int index = 1; + for (Exception exception : errors) { + message.append(index++) + .append(". ") + .append(exception.getClass().getSimpleName()) + .append(": ") + .append(exception.getMessage()) + .append("\n"); + } + return message.toString(); + } } From 22d7a085cdaceacc6e650e27d3750d501c1c1430 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 18 Sep 2025 08:38:33 +0800 Subject: [PATCH 119/129] update version --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- springboot-starter/src/main/resources/META-INF/banner.txt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 0056569b..60de5e15 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.17 + 2.10.18 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 5895ebb2..1a0974f8 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.17 + 2.10.18 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 8e419d6c..f00caecc 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.17 + 2.10.18 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 0bc93512..6a3afe7f 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.17 + 2.10.18 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index bcf442e0..c828fe84 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.17 + 2.10.18 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 710d2322..4dc5b9a6 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.17 + 2.10.18 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index e43fe65a..bf0753be 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.16 +CodingApi SpringBoot-Starter 2.10.18 springboot version (${spring-boot.version}) ------------------------------------------------------ From 155c10b7f18fefb8b77453194c41bb1e668c6a93 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 22 Oct 2025 16:24:34 +0800 Subject: [PATCH 120/129] #157 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- .../enhancer/DataPermissionSQLEnhancer.java | 45 +++++++ .../DataAuthorizationContextTest.java | 115 ++++++------------ .../src/test/resources/application.properties | 2 + springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/META-INF/banner.txt | 2 +- 10 files changed, 93 insertions(+), 83 deletions(-) diff --git a/pom.xml b/pom.xml index 60de5e15..14826050 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.18 + 2.10.19 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 1a0974f8..2feaea8f 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.18 + 2.10.19 springboot-starter-data-authorization diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java index 3c39d992..3915d39b 100644 --- a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java @@ -5,6 +5,8 @@ import com.codingapi.springboot.authorization.handler.RowHandler; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.InExpression; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Statement; @@ -100,6 +102,49 @@ private void enhanceDataPermissionInSelect(PlainSelect plainSelect) throws Excep } } } + + Expression expression = plainSelect.getWhere(); + this.handlerSubSelect(expression); + } + + private void handlerSubSelect(Expression expression) throws Exception { + if(expression!=null){ + if(expression instanceof AndExpression){ + AndExpression andExpression = (AndExpression) expression; + Expression leftExpression = andExpression.getLeftExpression(); + Expression rightExpression = andExpression.getRightExpression(); + + this.handlerSubSelect(leftExpression); + this.handlerSubSelect(rightExpression); + + } + if(expression instanceof OrExpression){ + OrExpression orExpression = (OrExpression) expression; + Expression leftExpression = orExpression.getLeftExpression(); + Expression rightExpression = orExpression.getRightExpression(); + + this.handlerSubSelect(leftExpression); + this.handlerSubSelect(rightExpression); + } + + if(expression instanceof InExpression){ + InExpression inExpression = (InExpression) expression; + Expression leftExpression = inExpression.getLeftExpression(); + Expression rightExpression = inExpression.getRightExpression(); + + this.handlerSubSelect(leftExpression); + this.handlerSubSelect(rightExpression); + } + + if(expression instanceof ParenthesedSelect){ + ParenthesedSelect parenthesedSelect = (ParenthesedSelect) expression; + this.enhanceDataPermissionInSelect(parenthesedSelect.getPlainSelect()); + } + + if(expression instanceof PlainSelect){ + this.enhanceDataPermissionInSelect((PlainSelect) expression); + } + } } diff --git a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationContextTest.java b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationContextTest.java index 3dd25040..70fa0f8a 100644 --- a/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationContextTest.java +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationContextTest.java @@ -1,13 +1,11 @@ package com.codingapi.springboot.authorization; import com.codingapi.springboot.authorization.current.CurrentUser; -import com.codingapi.springboot.authorization.enhancer.DataPermissionSQLEnhancer; import com.codingapi.springboot.authorization.entity.Depart; import com.codingapi.springboot.authorization.entity.Unit; import com.codingapi.springboot.authorization.entity.User; import com.codingapi.springboot.authorization.filter.DefaultDataAuthorizationFilter; import com.codingapi.springboot.authorization.handler.Condition; -import com.codingapi.springboot.authorization.handler.RowHandler; import com.codingapi.springboot.authorization.interceptor.SQLRunningContext; import com.codingapi.springboot.authorization.mask.ColumnMaskContext; import com.codingapi.springboot.authorization.mask.impl.BankCardMask; @@ -17,14 +15,6 @@ import com.codingapi.springboot.authorization.repository.UnitRepository; import com.codingapi.springboot.authorization.repository.UserRepository; import lombok.extern.slf4j.Slf4j; -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.parser.CCJSqlParserUtil; -import net.sf.jsqlparser.schema.Column; -import net.sf.jsqlparser.statement.Statement; -import net.sf.jsqlparser.statement.select.PlainSelect; -import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectItem; -import net.sf.jsqlparser.statement.select.SelectItemVisitor; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -37,7 +27,6 @@ import org.springframework.test.annotation.Rollback; import java.time.LocalDate; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -280,74 +269,43 @@ public boolean supportColumnAuthorization(String tableName, String columnName, O } - -// @Test + @Test @Order(4) - void test4() throws Exception{ - String sql = "SELECT\n" + - "\tt.* \n" + - "FROM\n" + - "\t(\n" + - "\t\tSELECT\n" + - "\t\t\tUNYiV.id AS '历史工作经历编号',\n" + - "\t\t\tUNYiV.company_name AS '历史工作单位',\n" + - "\t\t\tUNYiV.depart_name AS '历史工作部门',\n" + - "\t\t\tUNYiV.post_name AS '历史工作岗位',\n" + - "\t\t\tUNYiV.start_date AS '开始时间',\n" + - "\t\t\tUNYiV.end_date AS '结束时间',\n" + - "\t\t\towasH.员工编号 AS '员工编号',\n" + - "\t\t\towasH.员工姓名 AS '员工姓名',\n" + - "\t\t\towasH.员工生日 AS '员工生日',\n" + - "\t\t\towasH.员工地址 AS '员工地址',\n" + - "\t\t\towasH.身份证号码 AS '身份证号码',\n" + - "\t\t\towasH.手机号 AS '手机号',\n" + - "\t\t\towasH.部门编号 AS '部门编号',\n" + - "\t\t\towasH.岗位编号 AS '岗位编号',\n" + - "\t\t\towasH.任现职编号 AS '任现职编号',\n" + - "\t\t\towasH.社团编号 AS '社团编号',\n" + - "\t\t\towasH.社团名称 AS '社团名称',\n" + - "\t\t\towasH.创建时间 AS '创建时间' \n" + - "\t\tFROM\n" + - "\t\t\tt_work AS pehMS,\n" + - "\t\t\tt_employee AS OGwG7,\n" + - "\t\t\tt_work_history AS UNYiV,\n" + - "\t\t\t(\n" + - "\t\t\t\tSELECT\n" + - "\t\t\t\t\tWXJj8.id AS '员工编号',\n" + - "\t\t\t\t\tWXJj8.NAME AS '员工姓名',\n" + - "\t\t\t\t\tWXJj8.birth_date AS '员工生日',\n" + - "\t\t\t\t\tWXJj8.address AS '员工地址',\n" + - "\t\t\t\t\tWXJj8.id_card AS '身份证号码',\n" + - "\t\t\t\t\tWXJj8.phone AS '手机号',\n" + - "\t\t\t\t\tWXJj8.depart_id AS '部门编号',\n" + - "\t\t\t\t\tWXJj8.post_id AS '岗位编号',\n" + - "\t\t\t\t\tWXJj8.work_id AS '任现职编号',\n" + - "\t\t\t\t\trnGD4.id AS '社团编号',\n" + - "\t\t\t\t\trnGD4.NAME AS '社团名称',\n" + - "\t\t\t\t\trnGD4.create_date AS '创建时间' \n" + - "\t\t\t\tFROM\n" + - "\t\t\t\t\tt_employee AS WXJj8,\n" + - "\t\t\t\t\tt_league_employee AS dEj96,\n" + - "\t\t\t\t\tt_league AS rnGD4 \n" + - "\t\t\t\tWHERE\n" + - "\t\t\t\t\trnGD4.id < 100 \n" + - "\t\t\t\t\tAND dEj96.employee_id = WXJj8.id \n" + - "\t\t\t\t\tAND dEj96.league_id = rnGD4.id \n" + - "\t\t\t\t\tAND 1 = 1 \n" + - "\t\t\t) AS owasH \n" + - "\t\tWHERE\n" + - "\t\t\tUNYiV.employee_id = OGwG7.id \n" + - "\t\t\tAND OGwG7.work_id = pehMS.id \n" + - "\t\t\tAND owasH.任现职编号 = pehMS.id \n" + - "\t\t\tAND 1 = 1 \n" + - "\t) AS t , t_employee AS e where t.员工编号 = e.id and e.id = 1"; + void test4() throws Exception { + + unitRepository.deleteAll(); + departRepository.deleteAll(); + userRepository.deleteAll(); + + Unit rootUnit = new Unit("Coding总公司"); + unitRepository.save(rootUnit); + + Unit sdUnit = new Unit("Coding山东分公司", rootUnit.getId()); + unitRepository.save(sdUnit); + + Depart jgbDepart = new Depart("Coding架构部", rootUnit.getId()); + departRepository.save(jgbDepart); + + Depart xmbDepart = new Depart("Coding项目部", sdUnit.getId()); + departRepository.save(xmbDepart); + + User lorne = new User("lorne", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", jgbDepart); + User bob = new User("bob", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", xmbDepart); + User tom = new User("tom", LocalDate.parse("1991-01-01"), "beijing", "110105199003078999", "13812345678", xmbDepart); + + userRepository.save(lorne); + userRepository.save(bob); + userRepository.save(tom); + + String sql = "select * from t_user where phone like '%1%' and id > 1 and depart_id in (select id from t_depart where id > 0)"; DataAuthorizationContext.getInstance().clearDataAuthorizationFilters(); DataAuthorizationContext.getInstance().addDataAuthorizationFilter(new DefaultDataAuthorizationFilter() { @Override public Condition rowAuthorization(String tableName, String tableAlias) { - return super.rowAuthorization(tableName, tableAlias); + String conditionTemplate = "%s.id > -100 "; + return Condition.formatCondition(conditionTemplate, tableAlias); } @Override @@ -358,18 +316,23 @@ public T columnAuthorization(String tableName, String columnName, T value) { @Override public boolean supportColumnAuthorization(String tableName, String columnName, Object value) { - return true; + if ("t_depart".equalsIgnoreCase(tableName)) { + return true; + } + return false; } @Override public boolean supportRowAuthorization(String tableName, String tableAlias) { - return true; + if ("t_depart".equalsIgnoreCase(tableName)) { + return true; + } + return false; } }); - List> data = jdbcTemplate.queryForList(sql); -// System.out.println(data); + System.out.println(data); } diff --git a/springboot-starter-data-authorization/src/test/resources/application.properties b/springboot-starter-data-authorization/src/test/resources/application.properties index 4e944839..f5ac2519 100644 --- a/springboot-starter-data-authorization/src/test/resources/application.properties +++ b/springboot-starter-data-authorization/src/test/resources/application.properties @@ -11,3 +11,5 @@ spring.jpa.show-sql=true #spring.datasource.password=lorne4j#2024 logging.level.com.codingapi.springboot.authorization=debug + +codingapi.data-authorization.show-sql=true \ No newline at end of file diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index f00caecc..673bd32c 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.18 + 2.10.19 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 6a3afe7f..795ce8c9 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.18 + 2.10.19 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index c828fe84..8f40150f 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.18 + 2.10.19 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 4dc5b9a6..a676e449 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.18 + 2.10.19 springboot-starter diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index bf0753be..a0f70a7f 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.18 +CodingApi SpringBoot-Starter 2.10.19 springboot version (${spring-boot.version}) ------------------------------------------------------ From 5d50d9243edfeefe30ede1a86931b6e8fd59ea71 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 14 Nov 2025 23:58:11 +0800 Subject: [PATCH 121/129] fix postForm --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../springboot/framework/rest/HttpClient.java | 2 +- .../framework/rest/HttpRequest.java | 4 ++-- .../springboot/framework/rest/RestClient.java | 2 +- .../framework/rest/SessionClient.java | 4 ++-- .../framework/rest/param/RestParam.java | 19 +++++++++++++++++-- .../src/main/resources/META-INF/banner.txt | 2 +- 12 files changed, 30 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index 14826050..56387c22 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.19 + 2.10.20 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 2feaea8f..5edb0924 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.19 + 2.10.20 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 673bd32c..d297d9f7 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.19 + 2.10.20 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 795ce8c9..66f96160 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.19 + 2.10.20 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 8f40150f..0230787a 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.19 + 2.10.20 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index a676e449..8af46c7e 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.19 + 2.10.20 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/HttpClient.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/HttpClient.java index 4484b032..b91377b2 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/HttpClient.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/HttpClient.java @@ -31,7 +31,7 @@ public String post(String url, HttpHeaders headers, JSON jsonObject) { return httpRequest.getPostRequest(url, headers, jsonObject).execute(); } - public String post(String url, HttpHeaders headers, MultiValueMap formData) { + public String post(String url, HttpHeaders headers, MultiValueMap formData) { return httpRequest.getPostRequest(url, headers, formData).execute(); } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/HttpRequest.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/HttpRequest.java index f9ea8a71..025571dc 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/HttpRequest.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/HttpRequest.java @@ -129,8 +129,8 @@ public Request getPostRequest(String url, HttpHeaders headers, JSON jsonObject) }; } - public Request getPostRequest(String url, HttpHeaders headers, MultiValueMap formData) { - HttpEntity> httpEntity = new HttpEntity<>(formData, headers); + public Request getPostRequest(String url, HttpHeaders headers, MultiValueMap formData) { + HttpEntity> httpEntity = new HttpEntity<>(formData, headers); String requestUrl = requestHandler.handler(this,url ,HttpMethod.POST,headers,httpEntity); return () -> { ResponseEntity httpResponse = restTemplate.exchange(requestUrl, HttpMethod.POST, httpEntity, String.class); diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/RestClient.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/RestClient.java index 7aa14d62..61621744 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/RestClient.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/RestClient.java @@ -62,7 +62,7 @@ public String get(String api, HttpHeaders headers, MultiValueMap } public String get(String api, HttpHeaders headers, RestParam paramBuilder) { - return get(api, headers,paramBuilder!=null?paramBuilder.toFormRequest():null); + return get(api, headers,paramBuilder!=null?paramBuilder.toGetRequest():null); } public String get(String api, RestParam paramBuilder) { diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/SessionClient.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/SessionClient.java index ac4dc72a..24eab5f7 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/SessionClient.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/SessionClient.java @@ -92,11 +92,11 @@ public String getHtml(String url){ public String getHtml(String url, RestParam restParam){ httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - return httpClient.get(url,httpHeaders,restParam!=null?restParam.toFormRequest():null); + return httpClient.get(url,httpHeaders,restParam!=null?restParam.toGetRequest():null); } public String getJson(String url, RestParam restParam){ httpHeaders.setContentType(MediaType.APPLICATION_JSON); - return httpClient.get(url,httpHeaders,restParam!=null?restParam.toFormRequest():null); + return httpClient.get(url,httpHeaders,restParam!=null?restParam.toGetRequest():null); } } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java index 465d0b0f..5cd08ce9 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/rest/param/RestParam.java @@ -6,11 +6,13 @@ import org.springframework.util.MultiValueMap; import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; public class RestParam { private final JSONObject jsonBody; - private final MultiValueMap mapBody; + private final MultiValueMap mapBody; private RestParam() { this.jsonBody = new JSONObject(); @@ -42,10 +44,23 @@ public JSONObject toJsonRequest() { return jsonBody; } - public MultiValueMap toFormRequest() { + public MultiValueMap toFormRequest() { return mapBody; } + public MultiValueMap toGetRequest(){ + MultiValueMap request = new LinkedMultiValueMap<>(); + for(String key: mapBody.keySet()){ + List objectList = mapBody.get(key); + List stringList = new ArrayList<>(); + for (Object object:objectList){ + stringList.add(object.toString()); + } + request.put(key,stringList); + } + return request; + } + public RestParam add(String key, Object value) { return add(key, value, true); } diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt index a0f70a7f..a047cc68 100644 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ b/springboot-starter/src/main/resources/META-INF/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 2.10.19 +CodingApi SpringBoot-Starter 2.10.20 springboot version (${spring-boot.version}) ------------------------------------------------------ From 4cd0f32ffc40fe5c197e66335d3d64d4640029b0 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 27 Nov 2025 22:31:23 +0800 Subject: [PATCH 122/129] fix #160 --- pom.xml | 16 ++++++++- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- .../security/SecurityJwtApplicationTest.java | 19 +++++++++-- springboot-starter/pom.xml | 2 +- .../framework/AutoConfiguration.java | 15 +++++++- .../framework/utils/VersionUtils.java | 34 +++++++++++++++++++ .../src/main/resources/META-INF/banner.txt | 4 --- 10 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/VersionUtils.java delete mode 100644 springboot-starter/src/main/resources/META-INF/banner.txt diff --git a/pom.xml b/pom.xml index 56387c22..ce9b9d00 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.20 + 2.10.21 https://github.com/codingapi/springboot-framewrok springboot-parent @@ -235,6 +235,20 @@ -Xlint:deprecation + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + + ${project.version} + ${project.name} + + + + diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 5edb0924..0ffc5fd7 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.20 + 2.10.21 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index d297d9f7..8d6d3f51 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.20 + 2.10.21 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 66f96160..be8d18df 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.20 + 2.10.21 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 0230787a..f45583b9 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.20 + 2.10.21 springboot-starter-security diff --git a/springboot-starter-security/src/test/java/com/codingapi/springboot/security/SecurityJwtApplicationTest.java b/springboot-starter-security/src/test/java/com/codingapi/springboot/security/SecurityJwtApplicationTest.java index 3872eadc..cd78167b 100644 --- a/springboot-starter-security/src/test/java/com/codingapi/springboot/security/SecurityJwtApplicationTest.java +++ b/springboot-starter-security/src/test/java/com/codingapi/springboot/security/SecurityJwtApplicationTest.java @@ -7,14 +7,14 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.util.StringUtils; import java.nio.charset.StandardCharsets; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -27,6 +27,20 @@ public class SecurityJwtApplicationTest { @Autowired private MockMvc mockMvc; + + @Autowired + private PasswordEncoder passwordEncoder; + + + @Test + void encode(){ + String pwd1 = passwordEncoder.encode("123456"); + String pwd2 = passwordEncoder.encode("123456"); + System.out.println(pwd1); + System.out.println(pwd2); + assertNotEquals(pwd1,pwd2); + } + @Test void login() throws Exception { JSONObject json = new JSONObject(); @@ -37,6 +51,7 @@ void login() throws Exception { .contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); } + @Test void loginError() throws Exception { JSONObject json = new JSONObject(); diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 8af46c7e..a1ae63cf 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.20 + 2.10.21 springboot-starter diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/AutoConfiguration.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/AutoConfiguration.java index 2cfc0ae1..27fbca1c 100644 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/AutoConfiguration.java +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/AutoConfiguration.java @@ -1,8 +1,21 @@ package com.codingapi.springboot.framework; +import com.codingapi.springboot.framework.utils.VersionUtils; +import org.springframework.beans.factory.InitializingBean; import org.springframework.context.annotation.Configuration; @Configuration -public class AutoConfiguration { +public class AutoConfiguration implements InitializingBean { + @Override + public void afterPropertiesSet() throws Exception { + String version = VersionUtils.getDriverVersion(); + this.printBanner(version); + } + + public void printBanner(String version) { + System.out.println("------------------------------------------------------"); + System.out.println("\t\tCodingApi SpringBoot-Starter " + version); + System.out.println("------------------------------------------------------"); + } } diff --git a/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/VersionUtils.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/VersionUtils.java new file mode 100644 index 00000000..4c1cedb7 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/utils/VersionUtils.java @@ -0,0 +1,34 @@ +package com.codingapi.springboot.framework.utils; + +import java.io.InputStream; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +public class VersionUtils { + + public static String getJarVersion(Class clazz) { + try { + String classPath = clazz.getResource(clazz.getSimpleName() + ".class").toString(); + if (!classPath.startsWith("jar")) { + // 不是从 jar 启动的 + return "DEV"; + } + + String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF"; + try (InputStream inputStream = new java.net.URL(manifestPath).openStream()) { + Manifest manifest = new Manifest(inputStream); + Attributes attributes = manifest.getMainAttributes(); + return attributes.getValue("Implementation-Version"); + } + } catch (Exception e) { + return "UNKNOWN"; + } + } + + + public static String getDriverVersion(){ + return VersionUtils.getJarVersion(VersionUtils.class); + } + + +} diff --git a/springboot-starter/src/main/resources/META-INF/banner.txt b/springboot-starter/src/main/resources/META-INF/banner.txt deleted file mode 100644 index a047cc68..00000000 --- a/springboot-starter/src/main/resources/META-INF/banner.txt +++ /dev/null @@ -1,4 +0,0 @@ ------------------------------------------------------- -CodingApi SpringBoot-Starter 2.10.20 -springboot version (${spring-boot.version}) ------------------------------------------------------- From 69dea1b9af8fe88fa5ae9fb00e1a6c154275bd63 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 29 Nov 2025 20:10:20 +0800 Subject: [PATCH 123/129] fix #162 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../jpa/repository/DynamicSQLBuilder.java | 37 +++++++++++++------ .../fast/jpa/repository/FastRepository.java | 2 +- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 8 files changed, 33 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index ce9b9d00..07997448 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.21 + 2.10.22 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 0ffc5fd7..6feb3645 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.21 + 2.10.22 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 8d6d3f51..e18f226c 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.21 + 2.10.22 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java index 50dc3b5b..cc496f48 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java @@ -17,47 +17,62 @@ class DynamicSQLBuilder { private final PageRequest request; - private final Class clazz; private final List params = new ArrayList<>(); private int paramIndex = 1; + private final StringBuilder hql; + private final StringBuilder countHql ; public DynamicSQLBuilder(PageRequest request, Class clazz) { this.request = request; - this.clazz = clazz; + this.hql = new StringBuilder("FROM " + clazz.getSimpleName() + " WHERE "); + this.countHql = new StringBuilder("SELECT COUNT(1) FROM " + clazz.getSimpleName() + " WHERE "); + this.build(); } + public String getHQL(){ + return this.hql.toString(); + } + + public String getCountHQL(){ + return this.countHql.toString(); + } - public String getHQL() { - StringBuilder hql = new StringBuilder("FROM " + clazz.getSimpleName() + " WHERE "); + private void build() { + StringBuilder querySQL = new StringBuilder(); + StringBuilder orderSQL = new StringBuilder(); RequestFilter requestFilter = request.getRequestFilter(); if (requestFilter.hasFilter()) { List filters = requestFilter.getFilters(); for (int i = 0; i < filters.size(); i++) { Filter filter = filters.get(i); - this.buildSQL(filter, hql); + this.buildSQL(filter, querySQL); if (i != filters.size() - 1) { - hql.append(" AND "); + querySQL.append(" AND "); } } } Sort sort = request.getSort(); if (sort.isSorted()) { - hql.append(" ORDER BY "); + orderSQL.append(" ORDER BY "); List orders = sort.toList(); for (int i = 0; i < orders.size(); i++) { Sort.Order order = orders.get(i); - hql.append(order.getProperty()).append(" ").append(order.getDirection().name()); + orderSQL.append(order.getProperty()).append(" ").append(order.getDirection().name()); if (i != orders.size() - 1) { - hql.append(","); + orderSQL.append(","); } } } + this.hql.append(querySQL); + this.hql.append(orderSQL); + this.countHql.append(querySQL); + log.debug("hql:{}", hql); log.debug("params:{}", params); - return hql.toString(); + } @@ -139,7 +154,6 @@ private void buildSQL(Filter filter, StringBuilder hql) { params.add(Arrays.asList(filter.getValue())); paramIndex++; } - if (filter.isGreaterThan()) { hql.append(filter.getKey()).append(" > ?").append(paramIndex); params.add(filter.getValue()[0]); @@ -172,4 +186,5 @@ private void buildSQL(Filter filter, StringBuilder hql) { public Object[] getParams() { return params.toArray(); } + } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java index 1cc0c6c0..0a62bf7e 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java @@ -29,7 +29,7 @@ default Page pageRequest(PageRequest request) { if (request.hasFilter()) { Class clazz = getEntityClass(); DynamicSQLBuilder dynamicSQLBuilder = new DynamicSQLBuilder(request, clazz); - return dynamicPageQuery(dynamicSQLBuilder.getHQL(), request, dynamicSQLBuilder.getParams()); + return dynamicPageQuery(dynamicSQLBuilder.getHQL(),dynamicSQLBuilder.getCountHQL(), request, dynamicSQLBuilder.getParams()); } return findAll((org.springframework.data.domain.PageRequest) request); } diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index be8d18df..a6886aad 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.21 + 2.10.22 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index f45583b9..6011ff76 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.21 + 2.10.22 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index a1ae63cf..79d5ae11 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.21 + 2.10.22 springboot-starter From cb714b30565d2184114e5852f7f14f65b8180022 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Sat, 29 Nov 2025 20:11:29 +0800 Subject: [PATCH 124/129] fix #162 --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 07997448..8ea19da6 100644 --- a/pom.xml +++ b/pom.xml @@ -350,6 +350,7 @@ + From ffec91785bf3ca786aac55e970dbf40c84db836c Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Mon, 8 Dec 2025 14:42:10 +0800 Subject: [PATCH 125/129] fix #165 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../springboot/flow/content/FlowSession.java | 13 +++++++++++++ .../springboot/flow/service/FlowService.java | 11 +++++++++++ .../flow/service/impl/FlowRecallService.java | 16 ++++++++++++++-- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 9 files changed, 44 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 8ea19da6..d2139ba2 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.22 + 2.10.23 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 6feb3645..5ce64d4a 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.22 + 2.10.23 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index e18f226c..d225bc93 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.22 + 2.10.23 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index a6886aad..279e8c3c 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.22 + 2.10.23 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java index de4c7542..90b08007 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java @@ -283,6 +283,19 @@ public void recallFlow() { } + /** + * 撤回流程 + * @param backStartNode 是否退回到发起节点(仅限于流程创建者有效) + */ + public void recallFlow(boolean backStartNode) { + if (flowRecord == null) { + throw new IllegalArgumentException("flow record is null"); + } + FlowService flowService = loadFlowService(); + flowService.recall(flowRecord.getId(), currentOperator, backStartNode); + } + + private FlowService loadFlowService() { return (FlowService) getBean("flowService"); } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java index 2fd1c117..a4c7862f 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -281,6 +281,17 @@ public void recall(long recordId, IFlowOperator currentOperator) { flowRecallService.recall(recordId, currentOperator); } + /** + * 撤回流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param backStartNode 是否退回到发起节点(仅限于流程创建者有效) + */ + public void recall(long recordId, IFlowOperator currentOperator, boolean backStartNode) { + flowRecallService.recall(recordId, currentOperator,backStartNode); + } + /** * 删除流程 diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java index ca52652c..aeab8165 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java @@ -32,8 +32,9 @@ public class FlowRecallService { * * @param recordId 流程记录id * @param currentOperator 当前操作者 + * @param backStartNode 是否退回到发起节点(仅限于流程创建者有效) */ - public void recall(long recordId, IFlowOperator currentOperator) { + public void recall(long recordId, IFlowOperator currentOperator,boolean backStartNode) { FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService( flowWorkRepository, flowRecordRepository, @@ -51,7 +52,7 @@ public void recall(long recordId, IFlowOperator currentOperator) { FlowWork flowWork = flowRecordVerifyService.getFlowWork(); BindDataSnapshot bindDataSnapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); - if(flowRecordVerifyService.isCreateOperator()){ + if(backStartNode && flowRecordVerifyService.isCreateOperator()){ List records = flowRecordRepository.findFlowRecordByProcessId(flowRecord.getProcessId()); for(FlowRecord record:records){ if(!record.isStartRecord()) { @@ -88,4 +89,15 @@ public void recall(long recordId, IFlowOperator currentOperator) { IBindData bindData = bindDataSnapshot.toBindData(); EventPusher.push(new FlowApprovalEvent(FlowApprovalEvent.STATE_RECALL, flowRecord, currentOperator, flowWork, bindData), true); } + + + /** + * 撤回流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public void recall(long recordId, IFlowOperator currentOperator) { + this.recall(recordId, currentOperator, true); + } } diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 6011ff76..2c52fb8e 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.22 + 2.10.23 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 79d5ae11..4ff0d73e 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.22 + 2.10.23 springboot-starter From 2b4d311e9f1ddac2ae27a3ea0b94e5960f7c5828 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 11 Dec 2025 20:48:22 +0800 Subject: [PATCH 126/129] fix #167 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 7 +- .../DynamicEntityClassBuilder.java | 302 ++++++++++++++++++ .../classloader/DynamicEntityClassLoader.java | 60 ++++ .../DynamicEntityClassLoaderContext.java | 27 ++ .../fast/dynamic/DynamicEntityBuilder.java | 192 +++++++++++ .../fast/metadata/EntityMetaData.java | 133 ++++++++ .../dynamic/DynamicEntityBuilderTest.java | 62 ++++ springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 12 files changed, 787 insertions(+), 6 deletions(-) create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassBuilder.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoader.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoaderContext.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilder.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/EntityMetaData.java create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilderTest.java diff --git a/pom.xml b/pom.xml index d2139ba2..b40da990 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.23 + 2.10.24 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 5ce64d4a..3e663ee4 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.23 + 2.10.24 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index d225bc93..5aa8d575 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.23 + 2.10.24 4.0.0 @@ -20,6 +20,11 @@ + + net.bytebuddy + byte-buddy + + org.springframework.boot spring-boot-starter-web diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassBuilder.java new file mode 100644 index 00000000..21904e3d --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassBuilder.java @@ -0,0 +1,302 @@ +package com.codingapi.springboot.fast.classloader; + +import com.codingapi.springboot.fast.metadata.EntityMetaData; +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.description.annotation.AnnotationDescription; +import net.bytebuddy.description.modifier.Visibility; +import net.bytebuddy.dynamic.DynamicType; +import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; +import net.bytebuddy.implementation.FieldAccessor; +import org.hibernate.annotations.Comment; +import org.springframework.util.StringUtils; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 动态实体构建器 - 基于 EntityClass 元数据 + */ +public class DynamicEntityClassBuilder { + + /** + * 根据 EntityClass 构建动态实体 + */ + public static Class buildDynamicEntity(EntityMetaData entityMetaData) { + if (entityMetaData == null || entityMetaData.getClassName() == null) { + throw new IllegalArgumentException("Entity metadata cannot be null"); + } + + try { + DynamicType.Builder builder = new ByteBuddy() + .subclass(Object.class) + .name(entityMetaData.getClassName()) + .implement(Serializable.class) + .annotateType(buildEntityAnnotations(entityMetaData)); + + // 添加字段 + boolean hasPrimaryKey = false; + for (EntityMetaData.ColumnMeta column : entityMetaData.getColumns()) { + builder = addColumnField(builder, column); + if (column.isPrimaryKey()) { + hasPrimaryKey = true; + } + } + + // 如果没有主键,添加默认ID字段 + if (!hasPrimaryKey) { + builder = addDefaultIdField(builder); + } + + + Class clazz = builder.make() + .load(DynamicEntityClassBuilder.class.getClassLoader(), + ClassLoadingStrategy.Default.WRAPPER) + .getLoaded(); + + DynamicEntityClassLoaderContext.getInstance().registerClass(clazz); + + return clazz; + + } catch (Exception e) { + throw new RuntimeException("Failed to build dynamic entity: " + + entityMetaData.getClassName(), e); + } + } + + /** + * 构建实体类注解 + */ + private static AnnotationDescription[] buildEntityAnnotations(EntityMetaData entityMetaData) { + List annotations = new ArrayList<>(); + + // @Entity 注解 + annotations.add(AnnotationDescription.Builder.ofType(Entity.class).build()); + + // @Table 注解 + if (entityMetaData.getTable() != null) { + AnnotationDescription.Builder tableBuilder = + AnnotationDescription.Builder.ofType(Table.class); + + EntityMetaData.TableMeta tableMeta = entityMetaData.getTable(); + if (tableMeta.getName() != null && !tableMeta.getName().isEmpty()) { + tableBuilder = tableBuilder.define("name", tableMeta.getName()); + } + if (tableMeta.getCatalog() != null && !tableMeta.getCatalog().isEmpty()) { + tableBuilder = tableBuilder.define("catalog", tableMeta.getCatalog()); + } + if (tableMeta.getSchema() != null && !tableMeta.getSchema().isEmpty()) { + tableBuilder = tableBuilder.define("schema", tableMeta.getSchema()); + } + + annotations.add(tableBuilder.build()); + } + + // @Comment 注解 - 注释应该放在类上,而不是表注解上 + if (entityMetaData.getTable() != null && StringUtils.hasText(entityMetaData.getTable().getComment())) { + AnnotationDescription.Builder commentBuilder = + AnnotationDescription.Builder.ofType(Comment.class); + + EntityMetaData.TableMeta tableMeta = entityMetaData.getTable(); + commentBuilder = commentBuilder.define("value", tableMeta.getComment()); + annotations.add(commentBuilder.build()); + } + + return annotations.toArray(new AnnotationDescription[0]); + } + + /** + * 添加字段 + */ + private static DynamicType.Builder addColumnField(DynamicType.Builder builder, + EntityMetaData.ColumnMeta columnMeta) { + // 确定字段类型 + Class fieldType = columnMeta.getType(); + + // 构建字段名(转换驼峰命名) + String fieldName = convertToCamelCase(columnMeta.getName()); + + + + // 构建字段注解 + List fieldAnnotations = + buildFieldAnnotations(columnMeta, fieldName); + + // 开始定义字段 + DynamicType.Builder fieldBuilder = builder; + + + if (fieldAnnotations.isEmpty()) { + fieldBuilder = fieldBuilder.defineField(fieldName, fieldType, Visibility.PRIVATE); + }else { + fieldBuilder = fieldBuilder.defineField(fieldName, fieldType, Visibility.PRIVATE) + .annotateField(fieldAnnotations.toArray(new AnnotationDescription[0])); + } + + // 添加 getter 和 setter + String capitalizedFieldName = capitalize(fieldName); + String getterName = "get" + capitalizedFieldName; + String setterName = "set" + capitalizedFieldName; + + // 布尔类型特殊处理 + if (fieldType == Boolean.class || fieldType == Boolean.TYPE) { + getterName = "is" + capitalizedFieldName; + } + + fieldBuilder = fieldBuilder + .defineMethod(getterName, fieldType, Visibility.PUBLIC) + .intercept(FieldAccessor.ofField(fieldName)); + + fieldBuilder = fieldBuilder + .defineMethod(setterName, void.class, Visibility.PUBLIC) + .withParameter(fieldType) + .intercept(FieldAccessor.ofField(fieldName)); + + return fieldBuilder; + } + + /** + * 构建字段注解 + */ + private static List buildFieldAnnotations( + EntityMetaData.ColumnMeta columnMeta, String fieldName) { + + List annotations = new ArrayList<>(); + + // @Id 注解 + if (columnMeta.isPrimaryKey()) { + annotations.add(AnnotationDescription.Builder.ofType(Id.class).build()); + + // @GeneratedValue 注解 + if (columnMeta.getGeneratedValue() != null) { + EntityMetaData.GeneratedValueMeta genMeta = columnMeta.getGeneratedValue(); + AnnotationDescription.Builder genBuilder = + AnnotationDescription.Builder.ofType(GeneratedValue.class); + + if (genMeta.getStrategy() != null) { + genBuilder = genBuilder.define("strategy", genMeta.getStrategy()); + } + + if (genMeta.getGenerator() != null && !genMeta.getGenerator().isEmpty()) { + genBuilder = genBuilder.define("generator", genMeta.getGenerator()); + } + + annotations.add(genBuilder.build()); + } + } + + // @Column 注解 + AnnotationDescription.Builder columnBuilder = + AnnotationDescription.Builder.ofType(Column.class); + + columnBuilder = columnBuilder + .define("name", columnMeta.getName()) + .define("nullable", columnMeta.isNullable()) + .define("unique", columnMeta.isUnique()) + .define("insertable", columnMeta.isInsertable()) + .define("updatable", columnMeta.isUpdatable()); + + if (columnMeta.getLength() > 0) { + columnBuilder = columnBuilder.define("length", columnMeta.getLength()); + } + if (columnMeta.getPrecision() > 0) { + columnBuilder = columnBuilder.define("precision", columnMeta.getPrecision()); + } + if (columnMeta.getScale() > 0) { + columnBuilder = columnBuilder.define("scale", columnMeta.getScale()); + } + if (columnMeta.getColumnDefinition() != null && + !columnMeta.getColumnDefinition().isEmpty()) { + columnBuilder = columnBuilder.define("columnDefinition", + columnMeta.getColumnDefinition()); + } + + annotations.add(columnBuilder.build()); + + // @Comment 注解 + if (StringUtils.hasText(columnMeta.getComment())) { + annotations.add(AnnotationDescription.Builder.ofType(Comment.class) + .define("value", columnMeta.getComment()) + .build()); + } + + return annotations; + } + + /** + * 添加默认ID字段 - 修正版本 + */ + private static DynamicType.Builder addDefaultIdField(DynamicType.Builder builder) { + + + // 创建字段注解 + List fieldAnnotations = new ArrayList<>(); + fieldAnnotations.add(AnnotationDescription.Builder.ofType(Id.class).build()); + + // @GeneratedValue 注解 + AnnotationDescription.Builder genBuilder = + AnnotationDescription.Builder.ofType(GeneratedValue.class); + genBuilder = genBuilder.define("strategy", GenerationType.IDENTITY); + fieldAnnotations.add(genBuilder.build()); + + // @Column 注解 + AnnotationDescription.Builder columnBuilder = + AnnotationDescription.Builder.ofType(Column.class); + columnBuilder = columnBuilder + .define("name", "id") + .define("nullable", false); + fieldAnnotations.add(columnBuilder.build()); + + // 应用字段注解 + builder = builder.defineField("id", Long.class, Visibility.PRIVATE).annotateField(fieldAnnotations.toArray(new AnnotationDescription[0])); + + // 添加 getter 和 setter + builder = builder + .defineMethod("getId", Long.class, Visibility.PUBLIC) + .intercept(FieldAccessor.ofField("id")) + .defineMethod("setId", void.class, Visibility.PUBLIC) + .withParameter(Long.class) + .intercept(FieldAccessor.ofField("id")); + + return builder; + } + + /** + * 转换为驼峰命名 + */ + private static String convertToCamelCase(String name) { + if (name == null || name.isEmpty()) { + return name; + } + + // 处理下划线命名 + if (name.contains("_")) { + StringBuilder result = new StringBuilder(); + String[] parts = name.split("_"); + if (parts.length > 0) { + result.append(parts[0].toLowerCase()); + + for (int i = 1; i < parts.length; i++) { + if (!parts[i].isEmpty()) { + result.append(Character.toUpperCase(parts[i].charAt(0))); + if (parts[i].length() > 1) { + result.append(parts[i].substring(1).toLowerCase()); + } + } + } + } + return result.toString(); + } + + // 已经是驼峰命名,首字母小写 + return Character.toLowerCase(name.charAt(0)) + name.substring(1); + } + + private static String capitalize(String str) { + if (str == null || str.isEmpty()) { + return str; + } + return Character.toUpperCase(str.charAt(0)) + str.substring(1); + } +} \ No newline at end of file diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoader.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoader.java new file mode 100644 index 00000000..202a80dc --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoader.java @@ -0,0 +1,60 @@ +package com.codingapi.springboot.fast.classloader; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +class DynamicEntityClassLoader extends ClassLoader { + + private final Map> dynamicClasses = new ConcurrentHashMap<>(); + + public DynamicEntityClassLoader(ClassLoader parent) { + super(parent); + } + + public void registerClass(String className, Class clazz) { + dynamicClasses.put(className, clazz); + } + + public void registerClass(Class clazz) { + this.registerClass(clazz.getName(), clazz); + } + + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + // 首先检查已加载的动态类 + if (dynamicClasses.containsKey(name)) { + return dynamicClasses.get(name); + } + // 委托给父类 + return super.findClass(name); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + return loadClass(name, false); + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + synchronized (getClassLoadingLock(name)) { + // 首先检查是否已经加载 + Class c = findLoadedClass(name); + if (c == null) { + // 检查是否是动态类 + if (dynamicClasses.containsKey(name)) { + c = dynamicClasses.get(name); + } else { + // 委托给父类 + c = super.loadClass(name, resolve); + } + } + + if (resolve) { + resolveClass(c); + } + return c; + } + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoaderContext.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoaderContext.java new file mode 100644 index 00000000..555e4917 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoaderContext.java @@ -0,0 +1,27 @@ +package com.codingapi.springboot.fast.classloader; + +import lombok.Getter; + +public class DynamicEntityClassLoaderContext { + + @Getter + private final static DynamicEntityClassLoaderContext instance = new DynamicEntityClassLoaderContext(); + + private final DynamicEntityClassLoader dynamicEntityClassLoader; + + private DynamicEntityClassLoaderContext(){ + dynamicEntityClassLoader = new DynamicEntityClassLoader(Thread.currentThread().getContextClassLoader() != null + ? Thread.currentThread().getContextClassLoader() + : getClass().getClassLoader()); + Thread.currentThread().setContextClassLoader(dynamicEntityClassLoader); + } + + public void registerClass(String className, Class clazz) { + dynamicEntityClassLoader.registerClass(className, clazz); + } + + public void registerClass(Class clazz) { + dynamicEntityClassLoader.registerClass(clazz); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilder.java new file mode 100644 index 00000000..2bda86c1 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilder.java @@ -0,0 +1,192 @@ +package com.codingapi.springboot.fast.dynamic; + +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.Dialect; +import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractor; +import org.hibernate.tool.schema.SourceType; +import org.hibernate.tool.schema.TargetType; +import org.hibernate.tool.schema.internal.ExceptionHandlerCollectingImpl; +import org.hibernate.tool.schema.spi.*; +import org.springframework.util.StringUtils; + +import java.util.*; + +public class DynamicEntityBuilder { + + private final Dialect dialect; + private final StandardServiceRegistry serviceRegistry; + private final SchemaManagementTool managementTool; + + public DynamicEntityBuilder(Class dialectClass, String jdbcUrl) { + this(dialectClass,jdbcUrl,null,null); + } + + public DynamicEntityBuilder(Class dialectClass, String jdbcUrl, String username, String password) { + try { + this.dialect = (Dialect) dialectClass.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new RuntimeException("Failed to instantiate dialect", e); + } + + StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder() + .applySetting(AvailableSettings.DIALECT, dialect.getClass().getName()) + .applySetting("hibernate.connection.url", jdbcUrl); + if (StringUtils.hasText(username)) { + builder.applySetting("hibernate.connection.username", username); + } + if (StringUtils.hasText(password)) { + builder.applySetting("hibernate.connection.password", password); + } + this.serviceRegistry = builder.build(); + this.managementTool = serviceRegistry.getService(SchemaManagementTool.class); + } + + private class ExecutionOptionsImpl implements ExecutionOptions { + + @Override + public Map getConfigurationValues() { + Map config = new HashMap<>(); + config.put(AvailableSettings.DIALECT, dialect.getClass().getName()); + return config; + } + + @Override + public boolean shouldManageNamespaces() { + return false; + } + + @Override + public ExceptionHandler getExceptionHandler() { + return new ExceptionHandlerCollectingImpl(); + } + } + + + private static class SourceDescriptorImpl implements SourceDescriptor { + + @Override + public SourceType getSourceType() { + return SourceType.METADATA; + } + + @Override + public ScriptSourceInput getScriptSourceInput() { + return new ScriptSourceInput() { + @Override + public void prepare() { + + } + + @Override + public List read(ImportSqlCommandExtractor importSqlCommandExtractor) { + return new ArrayList<>(); + } + + @Override + public void release() { + + } + }; + } + } + + private static class TargetDescriptorImpl implements TargetDescriptor { + private final List sqlCommands = new ArrayList<>(); + + @Override + public EnumSet getTargetTypes() { + return EnumSet.of(TargetType.SCRIPT); + } + + @Override + public ScriptTargetOutput getScriptTargetOutput() { + return new ScriptTargetOutput() { + @Override + public void prepare() { + + } + + @Override + public void accept(String command) { + sqlCommands.add(command); + } + + @Override + public void release() { + + } + }; + } + + public String getDDL() { + return String.join("\n", sqlCommands); + } + } + + public String generateDropTableDDL(Class entityClass) { + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + metadataSources.addAnnotatedClass(entityClass); + Metadata metadata = metadataSources.buildMetadata(); + TargetDescriptorImpl targetDescriptor = new TargetDescriptorImpl(); + + managementTool.getSchemaDropper(Collections.emptyMap()).doDrop(metadata, + new ExecutionOptionsImpl(), + new SourceDescriptorImpl(), + targetDescriptor); + + return targetDescriptor.getDDL(); + } + + public String generateCreateTableDDL(Class entityClass) { + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + metadataSources.addAnnotatedClass(entityClass); + Metadata metadata = metadataSources.buildMetadata(); + + TargetDescriptorImpl targetDescriptor = new TargetDescriptorImpl(); + + managementTool.getSchemaCreator(Collections.emptyMap()).doCreation(metadata, + new ExecutionOptionsImpl(), + new SourceDescriptorImpl(), + targetDescriptor); + return targetDescriptor.getDDL(); + } + + public String generateMigratorTableDDL(Class entityClass) { + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + metadataSources.addAnnotatedClass(entityClass); + Metadata metadata = metadataSources.buildMetadata(); + + TargetDescriptorImpl targetDescriptor = new TargetDescriptorImpl(); + + managementTool.getSchemaMigrator(Collections.emptyMap()).doMigration(metadata, + new ExecutionOptionsImpl(), + targetDescriptor); + return targetDescriptor.getDDL(); + } + + public List validatorTable(Class entityClass) { + ExceptionHandlerCollectingImpl exceptionHandler = new ExceptionHandlerCollectingImpl(); + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + metadataSources.addAnnotatedClass(entityClass); + Metadata metadata = metadataSources.buildMetadata(); + List exceptionList = new ArrayList<>(); + try { + managementTool.getSchemaValidator(Collections.emptyMap()).doValidation(metadata, + new ExecutionOptionsImpl() { + @Override + public ExceptionHandler getExceptionHandler() { + return exceptionHandler; + } + }); + } catch (Exception e) { + exceptionList.add(e); + } + exceptionList.addAll(exceptionHandler.getExceptions()); + return exceptionList; + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/EntityMetaData.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/EntityMetaData.java new file mode 100644 index 00000000..054c6571 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/EntityMetaData.java @@ -0,0 +1,133 @@ +package com.codingapi.springboot.fast.metadata; + +import com.codingapi.springboot.fast.classloader.DynamicEntityClassBuilder; +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.GenerationType; +import java.util.ArrayList; +import java.util.List; + +@Getter +public class EntityMetaData { + + private final String className; + private final TableMeta table; + private final List columns; + + public EntityMetaData(String className) { + this.className = className; + this.table = new TableMeta(); + this.columns = new ArrayList<>(); + } + + public void setTable(String name,String catalog,String schema,String comment){ + this.table.setName(name); + this.table.setCatalog(catalog); + this.table.setSchema(schema); + this.table.setComment(comment); + } + + public void setTable(String name,String comment){ + this.setTable(name,null,null,comment); + } + + public void setTable(String name){ + this.setTable(name,null,null,null); + } + + public void addPrimaryKeyColumn(Class type, String name, GenerationType strategy, String generator, String comment, boolean unique, boolean nullable, boolean insertable, + boolean updatable, String columnDefinition, int length, int precision, int scale){ + ColumnMeta column = new ColumnMeta(); + column.setType(type); + column.setName(name); + column.setPrimaryKey(true); + GeneratedValueMeta generatedValueMeta = new GeneratedValueMeta(); + generatedValueMeta.setGenerator(generator); + generatedValueMeta.setStrategy(strategy); + column.setGeneratedValue(generatedValueMeta); + column.setComment(comment); + column.setUnique(unique); + column.setNullable(nullable); + column.setInsertable(insertable); + column.setUpdatable(updatable); + column.setColumnDefinition(columnDefinition); + column.setLength(length); + column.setPrecision(precision); + column.setScale(scale); + this.columns.add(column); + } + + public void addColumn(Class type,String name,String comment,boolean unique,boolean nullable, boolean insertable, + boolean updatable,String columnDefinition, int length,int precision,int scale){ + ColumnMeta column = new ColumnMeta(); + column.setPrimaryKey(false); + column.setType(type); + column.setName(name); + column.setComment(comment); + column.setUnique(unique); + column.setNullable(nullable); + column.setInsertable(insertable); + column.setUpdatable(updatable); + column.setColumnDefinition(columnDefinition); + column.setLength(length); + column.setPrecision(precision); + column.setScale(scale); + this.columns.add(column); + } + + public void addColumn(Class type,String name,String comment){ + this.addColumn(type,name,comment,false,false,false,false,null,255,0,0); + } + + public void addColumn(Class type,String name){ + this.addColumn(type,name,null,false,false,false,false,null,255,0,0); + } + + public void addPrimaryKeyColumn(Class type,String name,GenerationType strategy){ + this.addPrimaryKeyColumn(type,name,strategy,null,null,false,false,false,false,null,255,0,0); + } + + public void addPrimaryKeyColumn(Class type,String name,GenerationType strategy,String comment){ + this.addPrimaryKeyColumn(type,name,strategy,null,comment,false,false,false,false,null,255,0,0); + } + + public Class buildClass(){ + return DynamicEntityClassBuilder.buildDynamicEntity(this); + } + + @Setter + @Getter + public static class TableMeta{ + private String name; + private String catalog; + private String schema; + private String comment; + } + + @Setter + @Getter + public static class ColumnMeta{ + private Class type; + private String name; + private boolean isPrimaryKey; + private GeneratedValueMeta generatedValue; + private String comment; + private boolean unique; + private boolean nullable; + private boolean insertable; + private boolean updatable; + private String columnDefinition; + private int length; + private int precision; + private int scale; + } + + @Setter + @Getter + public static class GeneratedValueMeta{ + private GenerationType strategy; + private String generator; + } + +} diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilderTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilderTest.java new file mode 100644 index 00000000..bedc0b2b --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilderTest.java @@ -0,0 +1,62 @@ +package com.codingapi.springboot.fast.dynamic; + +import com.codingapi.springboot.fast.entity.Demo; +import com.codingapi.springboot.fast.metadata.EntityMetaData; +import org.hibernate.dialect.H2Dialect; +import org.junit.jupiter.api.Test; + +import javax.persistence.GenerationType; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class DynamicEntityBuilderTest { + + @Test + void generateTableDDL() { + DynamicEntityBuilder dynamicEntityBuilder = new DynamicEntityBuilder(H2Dialect.class,"jdbc:h2:file:./test.db"); + List exceptions = dynamicEntityBuilder.validatorTable(Demo.class); + System.out.println(exceptions); + + String createDDL = dynamicEntityBuilder.generateCreateTableDDL(Demo.class); + System.out.println("createDDL:\n" + createDDL); + assertNotNull(createDDL); + + String dropDDL = dynamicEntityBuilder.generateDropTableDDL(Demo.class); + System.out.println("dropDDL:\n" + dropDDL); + assertNotNull(dropDDL); + + String migrateDDL = dynamicEntityBuilder.generateMigratorTableDDL(Demo.class); + System.out.println("migrateDDL:\n" + migrateDDL); + assertNotNull(migrateDDL); + } + + @Test + void dynamicGenerateTableDDL() { + DynamicEntityBuilder dynamicEntityBuilder = new DynamicEntityBuilder(H2Dialect.class,"jdbc:h2:file:./test.db"); + + EntityMetaData entityMetaData = new EntityMetaData("com.codingapi.entity.Test"); + entityMetaData.setTable("test"); + entityMetaData.addPrimaryKeyColumn(Long.class,"id", GenerationType.IDENTITY,"主键"); + entityMetaData.addColumn(String.class,"name","姓名"); + + Class entityClass = entityMetaData.buildClass(); + + List exceptions = dynamicEntityBuilder.validatorTable(entityClass); + System.out.println(exceptions); + assertFalse(exceptions.isEmpty()); + + String createDDL = dynamicEntityBuilder.generateCreateTableDDL(entityClass); + System.out.println("createDDL:\n" + createDDL); + assertNotNull(createDDL); + + String dropDDL = dynamicEntityBuilder.generateDropTableDDL(entityClass); + System.out.println("dropDDL:\n" + dropDDL); + assertNotNull(dropDDL); + + String migrateDDL = dynamicEntityBuilder.generateMigratorTableDDL(entityClass); + System.out.println("migrateDDL:\n" + migrateDDL); + assertNotNull(migrateDDL); + + } +} \ No newline at end of file diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 279e8c3c..dde287a6 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.23 + 2.10.24 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 2c52fb8e..0d06689e 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.23 + 2.10.24 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 4ff0d73e..d046a973 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.23 + 2.10.24 springboot-starter From bc04f4120f48571f237b1e7835acb045287830c7 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 11 Dec 2025 22:45:33 +0800 Subject: [PATCH 127/129] fix #167 --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../classloader/DynamicEntityClassLoader.java | 60 ----- .../DynamicEntityClassLoaderContext.java | 27 --- .../classloader/DynamicTableClassLoader.java | 158 ++++++++++++ .../DynamicTableGenerator.java} | 83 ++++++- .../fast/metadata/EntityMetaData.java | 133 ---------- .../TableEntityClassBuilder.java} | 184 ++++---------- .../fast/metadata/TableEntityMetadata.java | 228 ++++++++++++++++++ .../dynamic/DynamicEntityBuilderTest.java | 62 ----- .../generator/DynamicTableGeneratorTest.java | 61 +++++ springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 15 files changed, 576 insertions(+), 432 deletions(-) delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoader.java delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoaderContext.java create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicTableClassLoader.java rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/{dynamic/DynamicEntityBuilder.java => generator/DynamicTableGenerator.java} (72%) delete mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/EntityMetaData.java rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/{classloader/DynamicEntityClassBuilder.java => metadata/TableEntityClassBuilder.java} (50%) create mode 100644 springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/TableEntityMetadata.java delete mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilderTest.java create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorTest.java diff --git a/pom.xml b/pom.xml index b40da990..6481a056 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.24 + 2.10.25 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 3e663ee4..5079b2dc 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.24 + 2.10.25 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 5aa8d575..bd965f6d 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.24 + 2.10.25 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoader.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoader.java deleted file mode 100644 index 202a80dc..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoader.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.codingapi.springboot.fast.classloader; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -class DynamicEntityClassLoader extends ClassLoader { - - private final Map> dynamicClasses = new ConcurrentHashMap<>(); - - public DynamicEntityClassLoader(ClassLoader parent) { - super(parent); - } - - public void registerClass(String className, Class clazz) { - dynamicClasses.put(className, clazz); - } - - public void registerClass(Class clazz) { - this.registerClass(clazz.getName(), clazz); - } - - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - // 首先检查已加载的动态类 - if (dynamicClasses.containsKey(name)) { - return dynamicClasses.get(name); - } - // 委托给父类 - return super.findClass(name); - } - - @Override - public Class loadClass(String name) throws ClassNotFoundException { - return loadClass(name, false); - } - - @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - synchronized (getClassLoadingLock(name)) { - // 首先检查是否已经加载 - Class c = findLoadedClass(name); - if (c == null) { - // 检查是否是动态类 - if (dynamicClasses.containsKey(name)) { - c = dynamicClasses.get(name); - } else { - // 委托给父类 - c = super.loadClass(name, resolve); - } - } - - if (resolve) { - resolveClass(c); - } - return c; - } - } - -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoaderContext.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoaderContext.java deleted file mode 100644 index 555e4917..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassLoaderContext.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.codingapi.springboot.fast.classloader; - -import lombok.Getter; - -public class DynamicEntityClassLoaderContext { - - @Getter - private final static DynamicEntityClassLoaderContext instance = new DynamicEntityClassLoaderContext(); - - private final DynamicEntityClassLoader dynamicEntityClassLoader; - - private DynamicEntityClassLoaderContext(){ - dynamicEntityClassLoader = new DynamicEntityClassLoader(Thread.currentThread().getContextClassLoader() != null - ? Thread.currentThread().getContextClassLoader() - : getClass().getClassLoader()); - Thread.currentThread().setContextClassLoader(dynamicEntityClassLoader); - } - - public void registerClass(String className, Class clazz) { - dynamicEntityClassLoader.registerClass(className, clazz); - } - - public void registerClass(Class clazz) { - dynamicEntityClassLoader.registerClass(clazz); - } - -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicTableClassLoader.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicTableClassLoader.java new file mode 100644 index 00000000..cf182bf2 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicTableClassLoader.java @@ -0,0 +1,158 @@ +package com.codingapi.springboot.fast.classloader; + +import lombok.Getter; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 动态表的 ClassLoader + */ +public class DynamicTableClassLoader { + + @Getter + private final static DynamicTableClassLoader instance = new DynamicTableClassLoader(); + + private final $DynamicTableClassLoader dynamicTableClassLoader; + + private DynamicTableClassLoader() { + dynamicTableClassLoader = new $DynamicTableClassLoader(Thread.currentThread().getContextClassLoader() != null + ? Thread.currentThread().getContextClassLoader() + : getClass().getClassLoader()); + Thread.currentThread().setContextClassLoader(dynamicTableClassLoader); + } + + /** + * 注册类 + * @param className name + * @param clazz class + */ + public void registerClass(String className, Class clazz) { + dynamicTableClassLoader.registerClass(className, clazz); + } + + /** + * 注册类 + * @param clazz class + */ + public void registerClass(Class clazz) { + dynamicTableClassLoader.registerClass(clazz); + } + + /** + * 获取类 + * @param name className + * @return class + */ + public Class findClass(String name) throws ClassNotFoundException { + return dynamicTableClassLoader.findClass(name); + } + + /** + * 加载类 + * @param name className + * @param resolve resolve + * @return class + */ + public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + return dynamicTableClassLoader.loadClass(name, resolve); + } + + /** + * 清空动态类 + * @param name 类名称 + */ + public void cleanDynamicClass(String name) { + dynamicTableClassLoader.cleanClass(name); + } + + /** + * 获取全部的动态类 + */ + public Collection> getDynamicClasses(){ + return dynamicTableClassLoader.getDynamicClasses(); + } + + /** + * 获取全部动态类的名称 + */ + public Set getDynamicClassNames(){ + return dynamicTableClassLoader.getDynamicClassNames(); + } + + + /** + * $DynamicTableClassLoader + */ + private static class $DynamicTableClassLoader extends ClassLoader { + + private final Map> dynamicClasses = new ConcurrentHashMap<>(); + + public $DynamicTableClassLoader(ClassLoader parent) { + super(parent); + } + + public void registerClass(String className, Class clazz) { + dynamicClasses.put(className, clazz); + } + + public void registerClass(Class clazz) { + this.registerClass(clazz.getName(), clazz); + } + + public void cleanClass(String className) { + this.dynamicClasses.remove(className); + } + + public Collection> getDynamicClasses(){ + return dynamicClasses.values(); + } + + public Set getDynamicClassNames(){ + return dynamicClasses.keySet(); + } + + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + // 首先检查已加载的动态类 + if (dynamicClasses.containsKey(name)) { + return dynamicClasses.get(name); + } + // 委托给父类 + return super.findClass(name); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + return loadClass(name, false); + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + synchronized (getClassLoadingLock(name)) { + // 首先检查是否已经加载 + Class c = findLoadedClass(name); + if (c == null) { + // 检查是否是动态类 + if (dynamicClasses.containsKey(name)) { + c = dynamicClasses.get(name); + } else { + // 委托给父类 + c = super.loadClass(name, resolve); + } + } + + if (resolve) { + resolveClass(c); + } + return c; + } + } + + } + + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/generator/DynamicTableGenerator.java similarity index 72% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilder.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/generator/DynamicTableGenerator.java index 2bda86c1..2c636074 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/generator/DynamicTableGenerator.java @@ -1,4 +1,4 @@ -package com.codingapi.springboot.fast.dynamic; +package com.codingapi.springboot.fast.generator; import org.hibernate.boot.Metadata; import org.hibernate.boot.MetadataSources; @@ -15,17 +15,23 @@ import java.util.*; -public class DynamicEntityBuilder { +/** + * DynamicTableGenerator 数据库表动态构建器 + */ +public class DynamicTableGenerator { + /** + * 数据库方言 + */ private final Dialect dialect; private final StandardServiceRegistry serviceRegistry; private final SchemaManagementTool managementTool; - public DynamicEntityBuilder(Class dialectClass, String jdbcUrl) { + public DynamicTableGenerator(Class dialectClass, String jdbcUrl) { this(dialectClass,jdbcUrl,null,null); } - public DynamicEntityBuilder(Class dialectClass, String jdbcUrl, String username, String password) { + public DynamicTableGenerator(Class dialectClass, String jdbcUrl, String username, String password) { try { this.dialect = (Dialect) dialectClass.getDeclaredConstructor().newInstance(); } catch (Exception e) { @@ -65,7 +71,6 @@ public ExceptionHandler getExceptionHandler() { } } - private static class SourceDescriptorImpl implements SourceDescriptor { @Override @@ -96,10 +101,20 @@ public void release() { private static class TargetDescriptorImpl implements TargetDescriptor { private final List sqlCommands = new ArrayList<>(); + private final boolean executable; + + public TargetDescriptorImpl(boolean executable) { + this.executable = executable; + } @Override public EnumSet getTargetTypes() { - return EnumSet.of(TargetType.SCRIPT); + EnumSet targetTypes = EnumSet.of(TargetType.SCRIPT); + if(executable) { + // 在数据库中执行 + targetTypes.add(TargetType.DATABASE); + } + return targetTypes; } @Override @@ -127,11 +142,26 @@ public String getDDL() { } } + /** + * 创建删除DDL语句 + * @param entityClass entity class对象 + * @return DDL + */ public String generateDropTableDDL(Class entityClass) { + return this.generateDropTableDDL(entityClass,false); + } + + /** + * 创建删除DDL语句 + * @param entityClass entity class对象 + * @param executable 是否数据中执行 + * @return DDL + */ + public String generateDropTableDDL(Class entityClass,boolean executable) { MetadataSources metadataSources = new MetadataSources(serviceRegistry); metadataSources.addAnnotatedClass(entityClass); Metadata metadata = metadataSources.buildMetadata(); - TargetDescriptorImpl targetDescriptor = new TargetDescriptorImpl(); + TargetDescriptorImpl targetDescriptor = new TargetDescriptorImpl(executable); managementTool.getSchemaDropper(Collections.emptyMap()).doDrop(metadata, new ExecutionOptionsImpl(), @@ -141,12 +171,27 @@ public String generateDropTableDDL(Class entityClass) { return targetDescriptor.getDDL(); } + /** + * 创建创建DDL语句 + * @param entityClass entity class对象 + * @return DDL + */ public String generateCreateTableDDL(Class entityClass) { + return this.generateCreateTableDDL(entityClass,false); + } + + /** + * 创建创建DDL语句 + * @param entityClass entity class对象 + * @param executable 是否数据中执行 + * @return DDL + */ + public String generateCreateTableDDL(Class entityClass,boolean executable) { MetadataSources metadataSources = new MetadataSources(serviceRegistry); metadataSources.addAnnotatedClass(entityClass); Metadata metadata = metadataSources.buildMetadata(); - TargetDescriptorImpl targetDescriptor = new TargetDescriptorImpl(); + TargetDescriptorImpl targetDescriptor = new TargetDescriptorImpl(executable); managementTool.getSchemaCreator(Collections.emptyMap()).doCreation(metadata, new ExecutionOptionsImpl(), @@ -155,12 +200,27 @@ public String generateCreateTableDDL(Class entityClass) { return targetDescriptor.getDDL(); } + /** + * 创建变更DDL语句,当数据不存在时则为创建,当数据中的表对象与entityClass不一致时则创建调整DDL + * @param entityClass entity class对象 + * @return DDL + */ public String generateMigratorTableDDL(Class entityClass) { + return this.generateMigratorTableDDL(entityClass,false); + } + + /** + * 创建变更DDL语句,当数据不存在时则为创建,当数据中的表对象与entityClass不一致时则创建调整DDL + * @param entityClass entity class对象 + * @param executable 是否数据中执行 + * @return DDL + */ + public String generateMigratorTableDDL(Class entityClass,boolean executable) { MetadataSources metadataSources = new MetadataSources(serviceRegistry); metadataSources.addAnnotatedClass(entityClass); Metadata metadata = metadataSources.buildMetadata(); - TargetDescriptorImpl targetDescriptor = new TargetDescriptorImpl(); + TargetDescriptorImpl targetDescriptor = new TargetDescriptorImpl(executable); managementTool.getSchemaMigrator(Collections.emptyMap()).doMigration(metadata, new ExecutionOptionsImpl(), @@ -168,6 +228,11 @@ public String generateMigratorTableDDL(Class entityClass) { return targetDescriptor.getDDL(); } + /** + * 检验对象与数据库是否一致,一致时无异常信息 + * @param entityClass entity class对象 + * @return 异常列表 + */ public List validatorTable(Class entityClass) { ExceptionHandlerCollectingImpl exceptionHandler = new ExceptionHandlerCollectingImpl(); MetadataSources metadataSources = new MetadataSources(serviceRegistry); diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/EntityMetaData.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/EntityMetaData.java deleted file mode 100644 index 054c6571..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/EntityMetaData.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.codingapi.springboot.fast.metadata; - -import com.codingapi.springboot.fast.classloader.DynamicEntityClassBuilder; -import lombok.Getter; -import lombok.Setter; - -import javax.persistence.GenerationType; -import java.util.ArrayList; -import java.util.List; - -@Getter -public class EntityMetaData { - - private final String className; - private final TableMeta table; - private final List columns; - - public EntityMetaData(String className) { - this.className = className; - this.table = new TableMeta(); - this.columns = new ArrayList<>(); - } - - public void setTable(String name,String catalog,String schema,String comment){ - this.table.setName(name); - this.table.setCatalog(catalog); - this.table.setSchema(schema); - this.table.setComment(comment); - } - - public void setTable(String name,String comment){ - this.setTable(name,null,null,comment); - } - - public void setTable(String name){ - this.setTable(name,null,null,null); - } - - public void addPrimaryKeyColumn(Class type, String name, GenerationType strategy, String generator, String comment, boolean unique, boolean nullable, boolean insertable, - boolean updatable, String columnDefinition, int length, int precision, int scale){ - ColumnMeta column = new ColumnMeta(); - column.setType(type); - column.setName(name); - column.setPrimaryKey(true); - GeneratedValueMeta generatedValueMeta = new GeneratedValueMeta(); - generatedValueMeta.setGenerator(generator); - generatedValueMeta.setStrategy(strategy); - column.setGeneratedValue(generatedValueMeta); - column.setComment(comment); - column.setUnique(unique); - column.setNullable(nullable); - column.setInsertable(insertable); - column.setUpdatable(updatable); - column.setColumnDefinition(columnDefinition); - column.setLength(length); - column.setPrecision(precision); - column.setScale(scale); - this.columns.add(column); - } - - public void addColumn(Class type,String name,String comment,boolean unique,boolean nullable, boolean insertable, - boolean updatable,String columnDefinition, int length,int precision,int scale){ - ColumnMeta column = new ColumnMeta(); - column.setPrimaryKey(false); - column.setType(type); - column.setName(name); - column.setComment(comment); - column.setUnique(unique); - column.setNullable(nullable); - column.setInsertable(insertable); - column.setUpdatable(updatable); - column.setColumnDefinition(columnDefinition); - column.setLength(length); - column.setPrecision(precision); - column.setScale(scale); - this.columns.add(column); - } - - public void addColumn(Class type,String name,String comment){ - this.addColumn(type,name,comment,false,false,false,false,null,255,0,0); - } - - public void addColumn(Class type,String name){ - this.addColumn(type,name,null,false,false,false,false,null,255,0,0); - } - - public void addPrimaryKeyColumn(Class type,String name,GenerationType strategy){ - this.addPrimaryKeyColumn(type,name,strategy,null,null,false,false,false,false,null,255,0,0); - } - - public void addPrimaryKeyColumn(Class type,String name,GenerationType strategy,String comment){ - this.addPrimaryKeyColumn(type,name,strategy,null,comment,false,false,false,false,null,255,0,0); - } - - public Class buildClass(){ - return DynamicEntityClassBuilder.buildDynamicEntity(this); - } - - @Setter - @Getter - public static class TableMeta{ - private String name; - private String catalog; - private String schema; - private String comment; - } - - @Setter - @Getter - public static class ColumnMeta{ - private Class type; - private String name; - private boolean isPrimaryKey; - private GeneratedValueMeta generatedValue; - private String comment; - private boolean unique; - private boolean nullable; - private boolean insertable; - private boolean updatable; - private String columnDefinition; - private int length; - private int precision; - private int scale; - } - - @Setter - @Getter - public static class GeneratedValueMeta{ - private GenerationType strategy; - private String generator; - } - -} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/TableEntityClassBuilder.java similarity index 50% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassBuilder.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/TableEntityClassBuilder.java index 21904e3d..48bf3d35 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/classloader/DynamicEntityClassBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/TableEntityClassBuilder.java @@ -1,6 +1,7 @@ -package com.codingapi.springboot.fast.classloader; +package com.codingapi.springboot.fast.metadata; -import com.codingapi.springboot.fast.metadata.EntityMetaData; +import com.codingapi.springboot.fast.classloader.DynamicTableClassLoader; +import javax.persistence.*; import net.bytebuddy.ByteBuddy; import net.bytebuddy.description.annotation.AnnotationDescription; import net.bytebuddy.description.modifier.Visibility; @@ -10,76 +11,69 @@ import org.hibernate.annotations.Comment; import org.springframework.util.StringUtils; -import javax.persistence.*; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** - * 动态实体构建器 - 基于 EntityClass 元数据 + * 动态实体构建器 - 基于 TableEntityMetadata 元数据 */ -public class DynamicEntityClassBuilder { +class TableEntityClassBuilder { - /** - * 根据 EntityClass 构建动态实体 - */ - public static Class buildDynamicEntity(EntityMetaData entityMetaData) { - if (entityMetaData == null || entityMetaData.getClassName() == null) { + private final TableEntityMetadata metadata; + private DynamicType.Builder builder; + + public TableEntityClassBuilder(TableEntityMetadata metadata) { + if (metadata == null || metadata.getClassName() == null) { throw new IllegalArgumentException("Entity metadata cannot be null"); } + this.metadata = metadata; + this.builder = new ByteBuddy() + .subclass(Object.class) + .name(metadata.getClassName()) + .implement(Serializable.class) + .annotateType(buildEntityAnnotations()); + } + public Class build() { try { - DynamicType.Builder builder = new ByteBuddy() - .subclass(Object.class) - .name(entityMetaData.getClassName()) - .implement(Serializable.class) - .annotateType(buildEntityAnnotations(entityMetaData)); - - // 添加字段 - boolean hasPrimaryKey = false; - for (EntityMetaData.ColumnMeta column : entityMetaData.getColumns()) { - builder = addColumnField(builder, column); - if (column.isPrimaryKey()) { - hasPrimaryKey = true; - } - } - - // 如果没有主键,添加默认ID字段 - if (!hasPrimaryKey) { - builder = addDefaultIdField(builder); - } - - + this.buildColumns(); Class clazz = builder.make() - .load(DynamicEntityClassBuilder.class.getClassLoader(), + .load(TableEntityClassBuilder.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); - - DynamicEntityClassLoaderContext.getInstance().registerClass(clazz); - + DynamicTableClassLoader.getInstance().registerClass(clazz); return clazz; } catch (Exception e) { throw new RuntimeException("Failed to build dynamic entity: " + - entityMetaData.getClassName(), e); + metadata.getClassName(), e); + } + } + + + private void buildColumns() { + for (TableEntityMetadata.ColumnMeta column : metadata.getColumns()) { + this.addColumnField(column); } } + /** * 构建实体类注解 */ - private static AnnotationDescription[] buildEntityAnnotations(EntityMetaData entityMetaData) { + private AnnotationDescription[] buildEntityAnnotations() { List annotations = new ArrayList<>(); // @Entity 注解 annotations.add(AnnotationDescription.Builder.ofType(Entity.class).build()); // @Table 注解 - if (entityMetaData.getTable() != null) { + if (metadata.getTable() != null) { AnnotationDescription.Builder tableBuilder = AnnotationDescription.Builder.ofType(Table.class); - EntityMetaData.TableMeta tableMeta = entityMetaData.getTable(); + TableEntityMetadata.TableMeta tableMeta = metadata.getTable(); if (tableMeta.getName() != null && !tableMeta.getName().isEmpty()) { tableBuilder = tableBuilder.define("name", tableMeta.getName()); } @@ -94,11 +88,11 @@ private static AnnotationDescription[] buildEntityAnnotations(EntityMetaData ent } // @Comment 注解 - 注释应该放在类上,而不是表注解上 - if (entityMetaData.getTable() != null && StringUtils.hasText(entityMetaData.getTable().getComment())) { + if (metadata.getTable() != null && StringUtils.hasText(metadata.getTable().getComment())) { AnnotationDescription.Builder commentBuilder = AnnotationDescription.Builder.ofType(Comment.class); - EntityMetaData.TableMeta tableMeta = entityMetaData.getTable(); + TableEntityMetadata.TableMeta tableMeta = metadata.getTable(); commentBuilder = commentBuilder.define("value", tableMeta.getComment()); annotations.add(commentBuilder.build()); } @@ -109,28 +103,20 @@ private static AnnotationDescription[] buildEntityAnnotations(EntityMetaData ent /** * 添加字段 */ - private static DynamicType.Builder addColumnField(DynamicType.Builder builder, - EntityMetaData.ColumnMeta columnMeta) { + private void addColumnField(TableEntityMetadata.ColumnMeta columnMeta) { // 确定字段类型 Class fieldType = columnMeta.getType(); - // 构建字段名(转换驼峰命名) - String fieldName = convertToCamelCase(columnMeta.getName()); - - + // 构建字段名 + String fieldName = columnMeta.getFieldName(); // 构建字段注解 - List fieldAnnotations = - buildFieldAnnotations(columnMeta, fieldName); - - // 开始定义字段 - DynamicType.Builder fieldBuilder = builder; - + List fieldAnnotations = this.buildFieldAnnotations(columnMeta); if (fieldAnnotations.isEmpty()) { - fieldBuilder = fieldBuilder.defineField(fieldName, fieldType, Visibility.PRIVATE); - }else { - fieldBuilder = fieldBuilder.defineField(fieldName, fieldType, Visibility.PRIVATE) + builder = builder.defineField(fieldName, fieldType, Visibility.PRIVATE); + } else { + builder = builder.defineField(fieldName, fieldType, Visibility.PRIVATE) .annotateField(fieldAnnotations.toArray(new AnnotationDescription[0])); } @@ -144,24 +130,20 @@ private static DynamicType.Builder addColumnField(DynamicType.Builder buil getterName = "is" + capitalizedFieldName; } - fieldBuilder = fieldBuilder - .defineMethod(getterName, fieldType, Visibility.PUBLIC) + builder = builder.defineMethod(getterName, fieldType, Visibility.PUBLIC) .intercept(FieldAccessor.ofField(fieldName)); - fieldBuilder = fieldBuilder - .defineMethod(setterName, void.class, Visibility.PUBLIC) + builder = builder.defineMethod(setterName, void.class, Visibility.PUBLIC) .withParameter(fieldType) .intercept(FieldAccessor.ofField(fieldName)); - return fieldBuilder; } /** * 构建字段注解 */ - private static List buildFieldAnnotations( - EntityMetaData.ColumnMeta columnMeta, String fieldName) { - + private List buildFieldAnnotations( + TableEntityMetadata.ColumnMeta columnMeta) { List annotations = new ArrayList<>(); // @Id 注解 @@ -170,7 +152,7 @@ private static List buildFieldAnnotations( // @GeneratedValue 注解 if (columnMeta.getGeneratedValue() != null) { - EntityMetaData.GeneratedValueMeta genMeta = columnMeta.getGeneratedValue(); + TableEntityMetadata.GeneratedValueMeta genMeta = columnMeta.getGeneratedValue(); AnnotationDescription.Builder genBuilder = AnnotationDescription.Builder.ofType(GeneratedValue.class); @@ -191,7 +173,7 @@ private static List buildFieldAnnotations( AnnotationDescription.Builder.ofType(Column.class); columnBuilder = columnBuilder - .define("name", columnMeta.getName()) + .define("name", columnMeta.getColumnName()) .define("nullable", columnMeta.isNullable()) .define("unique", columnMeta.isUnique()) .define("insertable", columnMeta.isInsertable()) @@ -224,76 +206,8 @@ private static List buildFieldAnnotations( return annotations; } - /** - * 添加默认ID字段 - 修正版本 - */ - private static DynamicType.Builder addDefaultIdField(DynamicType.Builder builder) { - - - // 创建字段注解 - List fieldAnnotations = new ArrayList<>(); - fieldAnnotations.add(AnnotationDescription.Builder.ofType(Id.class).build()); - - // @GeneratedValue 注解 - AnnotationDescription.Builder genBuilder = - AnnotationDescription.Builder.ofType(GeneratedValue.class); - genBuilder = genBuilder.define("strategy", GenerationType.IDENTITY); - fieldAnnotations.add(genBuilder.build()); - - // @Column 注解 - AnnotationDescription.Builder columnBuilder = - AnnotationDescription.Builder.ofType(Column.class); - columnBuilder = columnBuilder - .define("name", "id") - .define("nullable", false); - fieldAnnotations.add(columnBuilder.build()); - - // 应用字段注解 - builder = builder.defineField("id", Long.class, Visibility.PRIVATE).annotateField(fieldAnnotations.toArray(new AnnotationDescription[0])); - - // 添加 getter 和 setter - builder = builder - .defineMethod("getId", Long.class, Visibility.PUBLIC) - .intercept(FieldAccessor.ofField("id")) - .defineMethod("setId", void.class, Visibility.PUBLIC) - .withParameter(Long.class) - .intercept(FieldAccessor.ofField("id")); - - return builder; - } - - /** - * 转换为驼峰命名 - */ - private static String convertToCamelCase(String name) { - if (name == null || name.isEmpty()) { - return name; - } - - // 处理下划线命名 - if (name.contains("_")) { - StringBuilder result = new StringBuilder(); - String[] parts = name.split("_"); - if (parts.length > 0) { - result.append(parts[0].toLowerCase()); - - for (int i = 1; i < parts.length; i++) { - if (!parts[i].isEmpty()) { - result.append(Character.toUpperCase(parts[i].charAt(0))); - if (parts[i].length() > 1) { - result.append(parts[i].substring(1).toLowerCase()); - } - } - } - } - return result.toString(); - } - - // 已经是驼峰命名,首字母小写 - return Character.toLowerCase(name.charAt(0)) + name.substring(1); - } - private static String capitalize(String str) { + private String capitalize(String str) { if (str == null || str.isEmpty()) { return str; } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/TableEntityMetadata.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/TableEntityMetadata.java new file mode 100644 index 00000000..ff8588ae --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/TableEntityMetadata.java @@ -0,0 +1,228 @@ +package com.codingapi.springboot.fast.metadata; + +import javax.persistence.GenerationType; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +/** + * 表实体元数据 + */ +@Getter +public class TableEntityMetadata { + + /** + * 类名称 + */ + private final String className; + /** + * 数据库表信息 + */ + private final TableMeta table; + /** + * 字段信息 + */ + private final List columns; + + @Setter + @Getter + public static class TableMeta { + /** + * 数据库名称 + */ + private String name; + private String catalog; + private String schema; + /** + * 备注信息 + */ + private String comment; + } + + @Setter + @Getter + public static class ColumnMeta { + /** + * 字段类型 + */ + private Class type; + /** + * 表字段名称 + */ + private String columnName; + /** + * 类字段名称 + */ + private String fieldName; + /** + * 是否主键 + */ + private boolean isPrimaryKey; + /** + * 主键自增策略 + */ + private GeneratedValueMeta generatedValue; + /** + * 备注 + */ + private String comment; + /** + * 是否唯一 + */ + private boolean unique; + /** + * 是否为空 + */ + private boolean nullable; + /** + * 是否可以插入数据 + */ + private boolean insertable; + /** + * 是否可以更新数据 + */ + private boolean updatable; + /** + * 字段定义 + */ + private String columnDefinition; + /** + * 字段长度 + */ + private int length; + private int precision; + private int scale; + } + + @Setter + @Getter + public static class GeneratedValueMeta { + /** + * 自增长策略 + */ + private GenerationType strategy; + /** + * 自定义 + */ + private String generator; + } + + + /** + * 类名称 + * + * @param className 类名称 + */ + public TableEntityMetadata(String className) { + this.className = className; + this.table = new TableMeta(); + this.columns = new ArrayList<>(); + } + + + public void setTable(String name, String catalog, String schema, String comment) { + this.table.setName(name); + this.table.setCatalog(catalog); + this.table.setSchema(schema); + this.table.setComment(comment); + } + + public void setTable(String name, String comment) { + this.setTable(name, null, null, comment); + } + + public void setTable(String name) { + this.setTable(name, null, null, null); + } + + public void addPrimaryKeyColumn(Class type, String fieldName, String columnName, GenerationType strategy, + String generator, String comment, boolean unique, boolean nullable, + boolean insertable, boolean updatable, String columnDefinition, + int length, int precision, int scale) { + ColumnMeta column = new ColumnMeta(); + column.setType(type); + column.setFieldName(fieldName); + column.setColumnName(columnName); + column.setPrimaryKey(true); + GeneratedValueMeta generatedValueMeta = new GeneratedValueMeta(); + generatedValueMeta.setGenerator(generator); + generatedValueMeta.setStrategy(strategy); + column.setGeneratedValue(generatedValueMeta); + column.setComment(comment); + column.setUnique(unique); + column.setNullable(nullable); + column.setInsertable(insertable); + column.setUpdatable(updatable); + column.setColumnDefinition(columnDefinition); + column.setLength(length); + column.setPrecision(precision); + column.setScale(scale); + this.columns.add(column); + } + + public void addColumn(Class type, String fieldName, String columnName, String comment, + boolean unique, boolean nullable, boolean insertable, + boolean updatable, String columnDefinition, int length, + int precision, int scale) { + ColumnMeta column = new ColumnMeta(); + column.setPrimaryKey(false); + column.setType(type); + column.setFieldName(fieldName); + column.setColumnName(columnName); + column.setComment(comment); + column.setUnique(unique); + column.setNullable(nullable); + column.setInsertable(insertable); + column.setUpdatable(updatable); + column.setColumnDefinition(columnDefinition); + column.setLength(length); + column.setPrecision(precision); + column.setScale(scale); + this.columns.add(column); + } + + public void addColumn(Class type, String name, String comment) { + this.addColumn(type, name, name, comment, false, false, false, false, null, 255, 0, 0); + } + + public void addColumn(Class type, String name) { + this.addColumn(type, name, name, null, false, false, false, false, null, 255, 0, 0); + } + + public void addPrimaryKeyColumn(Class type, String name) { + this.addPrimaryKeyColumn(type, name, name, null, null, null, false, false, false, false, null, 255, 0, 0); + } + + public void addPrimaryKeyColumn(Class type, String name, GenerationType strategy) { + this.addPrimaryKeyColumn(type, name, name, strategy, null, null, false, false, false, false, null, 255, 0, 0); + } + + public void addPrimaryKeyColumn(Class type, String name, GenerationType strategy, String comment) { + this.addPrimaryKeyColumn(type, name, name, strategy, null, comment, false, false, false, false, null, 255, 0, 0); + } + + public void verify() { + if (columns.isEmpty()) { + throw new IllegalArgumentException("columns must not null."); + } + boolean hasPrimaryKey = false; + for (ColumnMeta column : columns) { + if (column.isPrimaryKey) { + hasPrimaryKey = true; + } + } + if (!hasPrimaryKey) { + throw new IllegalArgumentException("columns must has primaryKey."); + } + } + + public Class buildClass() { + this.verify(); + TableEntityClassBuilder builder = new TableEntityClassBuilder(this); + return builder.build(); + } + + +} diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilderTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilderTest.java deleted file mode 100644 index bedc0b2b..00000000 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/dynamic/DynamicEntityBuilderTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.codingapi.springboot.fast.dynamic; - -import com.codingapi.springboot.fast.entity.Demo; -import com.codingapi.springboot.fast.metadata.EntityMetaData; -import org.hibernate.dialect.H2Dialect; -import org.junit.jupiter.api.Test; - -import javax.persistence.GenerationType; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -class DynamicEntityBuilderTest { - - @Test - void generateTableDDL() { - DynamicEntityBuilder dynamicEntityBuilder = new DynamicEntityBuilder(H2Dialect.class,"jdbc:h2:file:./test.db"); - List exceptions = dynamicEntityBuilder.validatorTable(Demo.class); - System.out.println(exceptions); - - String createDDL = dynamicEntityBuilder.generateCreateTableDDL(Demo.class); - System.out.println("createDDL:\n" + createDDL); - assertNotNull(createDDL); - - String dropDDL = dynamicEntityBuilder.generateDropTableDDL(Demo.class); - System.out.println("dropDDL:\n" + dropDDL); - assertNotNull(dropDDL); - - String migrateDDL = dynamicEntityBuilder.generateMigratorTableDDL(Demo.class); - System.out.println("migrateDDL:\n" + migrateDDL); - assertNotNull(migrateDDL); - } - - @Test - void dynamicGenerateTableDDL() { - DynamicEntityBuilder dynamicEntityBuilder = new DynamicEntityBuilder(H2Dialect.class,"jdbc:h2:file:./test.db"); - - EntityMetaData entityMetaData = new EntityMetaData("com.codingapi.entity.Test"); - entityMetaData.setTable("test"); - entityMetaData.addPrimaryKeyColumn(Long.class,"id", GenerationType.IDENTITY,"主键"); - entityMetaData.addColumn(String.class,"name","姓名"); - - Class entityClass = entityMetaData.buildClass(); - - List exceptions = dynamicEntityBuilder.validatorTable(entityClass); - System.out.println(exceptions); - assertFalse(exceptions.isEmpty()); - - String createDDL = dynamicEntityBuilder.generateCreateTableDDL(entityClass); - System.out.println("createDDL:\n" + createDDL); - assertNotNull(createDDL); - - String dropDDL = dynamicEntityBuilder.generateDropTableDDL(entityClass); - System.out.println("dropDDL:\n" + dropDDL); - assertNotNull(dropDDL); - - String migrateDDL = dynamicEntityBuilder.generateMigratorTableDDL(entityClass); - System.out.println("migrateDDL:\n" + migrateDDL); - assertNotNull(migrateDDL); - - } -} \ No newline at end of file diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorTest.java new file mode 100644 index 00000000..2e09de95 --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorTest.java @@ -0,0 +1,61 @@ +package com.codingapi.springboot.fast.generator; + +import com.codingapi.springboot.fast.entity.Demo; +import com.codingapi.springboot.fast.metadata.TableEntityMetadata; +import javax.persistence.GenerationType; +import org.hibernate.dialect.H2Dialect; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class DynamicTableGeneratorTest { + + @Test + void generateTableDDL() { + DynamicTableGenerator dynamicTableGenerator = new DynamicTableGenerator(H2Dialect.class,"jdbc:h2:file:./test.db"); + List exceptions = dynamicTableGenerator.validatorTable(Demo.class); + System.out.println(exceptions); + + String createDDL = dynamicTableGenerator.generateCreateTableDDL(Demo.class); + System.out.println("createDDL:\n" + createDDL); + assertNotNull(createDDL); + + String dropDDL = dynamicTableGenerator.generateDropTableDDL(Demo.class); + System.out.println("dropDDL:\n" + dropDDL); + assertNotNull(dropDDL); + + String migrateDDL = dynamicTableGenerator.generateMigratorTableDDL(Demo.class); + System.out.println("migrateDDL:\n" + migrateDDL); + assertNotNull(migrateDDL); + } + + @Test + void dynamicGenerateTableDDL() { + DynamicTableGenerator dynamicTableGenerator = new DynamicTableGenerator(H2Dialect.class,"jdbc:h2:file:./test.db"); + + TableEntityMetadata tableEntityMetadata = new TableEntityMetadata("com.codingapi.entity.Test"); + tableEntityMetadata.setTable("test"); + tableEntityMetadata.addPrimaryKeyColumn(Long.class,"id", GenerationType.IDENTITY,"主键"); + tableEntityMetadata.addColumn(String.class,"name","姓名"); + + Class entityClass = tableEntityMetadata.buildClass(); + + List exceptions = dynamicTableGenerator.validatorTable(entityClass); + System.out.println(exceptions); + + String createDDL = dynamicTableGenerator.generateCreateTableDDL(entityClass); + System.out.println("createDDL:\n" + createDDL); + assertNotNull(createDDL); + + String dropDDL = dynamicTableGenerator.generateDropTableDDL(entityClass); + System.out.println("dropDDL:\n" + dropDDL); + assertNotNull(dropDDL); + + String migrateDDL = dynamicTableGenerator.generateMigratorTableDDL(entityClass); + System.out.println("migrateDDL:\n" + migrateDDL); + assertNotNull(migrateDDL); + + } +} \ No newline at end of file diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index dde287a6..5ca5cd4e 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.24 + 2.10.25 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 0d06689e..9f16cb54 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.24 + 2.10.25 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index d046a973..2e982604 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.24 + 2.10.25 springboot-starter From 4bde4e68a611315ba9e4d4648388c9d01e8a1e3f Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 12 Dec 2025 08:55:58 +0800 Subject: [PATCH 128/129] add DynamicTableGeneratorQueryTest --- .../fast/generator/DynamicTableGenerator.java | 14 ++-- .../DynamicTableGeneratorQueryTest.java | 71 +++++++++++++++++++ 2 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorQueryTest.java diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/generator/DynamicTableGenerator.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/generator/DynamicTableGenerator.java index 2c636074..91231ab8 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/generator/DynamicTableGenerator.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/generator/DynamicTableGenerator.java @@ -5,7 +5,6 @@ import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.AvailableSettings; -import org.hibernate.dialect.Dialect; import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractor; import org.hibernate.tool.schema.SourceType; import org.hibernate.tool.schema.TargetType; @@ -23,7 +22,7 @@ public class DynamicTableGenerator { /** * 数据库方言 */ - private final Dialect dialect; + private final Class dialect; private final StandardServiceRegistry serviceRegistry; private final SchemaManagementTool managementTool; @@ -32,14 +31,9 @@ public DynamicTableGenerator(Class dialectClass, String jdbcUrl) { } public DynamicTableGenerator(Class dialectClass, String jdbcUrl, String username, String password) { - try { - this.dialect = (Dialect) dialectClass.getDeclaredConstructor().newInstance(); - } catch (Exception e) { - throw new RuntimeException("Failed to instantiate dialect", e); - } - + this.dialect = dialectClass; StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder() - .applySetting(AvailableSettings.DIALECT, dialect.getClass().getName()) + .applySetting(AvailableSettings.DIALECT, dialect.getName()) .applySetting("hibernate.connection.url", jdbcUrl); if (StringUtils.hasText(username)) { builder.applySetting("hibernate.connection.username", username); @@ -56,7 +50,7 @@ private class ExecutionOptionsImpl implements ExecutionOptions { @Override public Map getConfigurationValues() { Map config = new HashMap<>(); - config.put(AvailableSettings.DIALECT, dialect.getClass().getName()); + config.put(AvailableSettings.DIALECT, dialect.getName()); return config; } diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorQueryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorQueryTest.java new file mode 100644 index 00000000..4d4dd64b --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorQueryTest.java @@ -0,0 +1,71 @@ +package com.codingapi.springboot.fast.generator; + +import com.codingapi.springboot.fast.jdbc.JdbcQuery; +import com.codingapi.springboot.fast.jdbc.JdbcQueryContext; +import com.codingapi.springboot.fast.jpa.JPAQuery; +import com.codingapi.springboot.fast.jpa.JpaQueryContext; +import com.codingapi.springboot.fast.metadata.TableEntityMetadata; +import javax.persistence.EntityManagerFactory; +import javax.persistence.GenerationType; +import org.hibernate.cfg.AvailableSettings; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.env.Environment; +import org.springframework.jdbc.core.JdbcTemplate; + +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@SpringBootTest +public class DynamicTableGeneratorQueryTest { + + @Autowired + private EntityManagerFactory entityManagerFactory; + + @Autowired + private Environment environment; + + @Autowired + private JdbcTemplate jdbcTemplate; + + + @Test + void generateThenUpdateQuery() throws ClassNotFoundException { + String dialect = entityManagerFactory.getProperties().get(AvailableSettings.DIALECT).toString(); + String jdbcUrl = environment.getProperty("spring.datasource.url"); + String username = environment.getProperty("spring.datasource.username"); + String password = environment.getProperty("spring.datasource.password"); + + DynamicTableGenerator dynamicTableGenerator = new DynamicTableGenerator(Class.forName(dialect), jdbcUrl, username, password); + + TableEntityMetadata tableEntityMetadata = new TableEntityMetadata("com.codingapi.springboot.fast.entity.Test"); + tableEntityMetadata.setTable("test"); + tableEntityMetadata.addPrimaryKeyColumn(Long.class, "id", GenerationType.IDENTITY, "主键"); + tableEntityMetadata.addColumn(String.class, "name", "姓名"); + + Class entityClass = tableEntityMetadata.buildClass(); + + // 创建表 + dynamicTableGenerator.generateMigratorTableDDL(entityClass, true); + + // 通过DynamicTableGenerator 动态创建的entity无法通过jpa的 EntityManager进行数据查询处理, 因为Entity不在JPA扫描支持的范围内。 + JPAQuery jpaQuery = JpaQueryContext.getInstance().getJPAQuery(); + assertThrows(Exception.class,()->{ + jpaQuery.listQuery(entityClass,"select t from com.codingapi.springboot.fast.entity.Test"); + }); + + // 插入数据 + jdbcTemplate.update("insert into test(name) values(?)", "小明"); + + // 查询数据 + JdbcQuery jdbcQuery = JdbcQueryContext.getInstance().getJdbcQuery(); + List> list = jdbcQuery.queryForMapList("select * from test"); + System.out.println(list); + assertFalse(list.isEmpty()); + + } +} \ No newline at end of file From e5680bd527f03ec4ba546e04db6f3fb1db5a7060 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Fri, 12 Dec 2025 08:58:12 +0800 Subject: [PATCH 129/129] update --- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../fast/jpa/{JPAQuery.java => JpaQuery.java} | 2 +- ...uration.java => JpaQueryConfiguration.java} | 10 +++++----- .../springboot/fast/jpa/JpaQueryContext.java | 6 +++--- ...ister.java => JpaQueryContextRegister.java} | 6 +++--- .../fast/jpa/repository/DynamicRepository.java | 18 +++++++++--------- .../springboot/fast/script/ScriptRuntime.java | 4 ++-- .../main/resources/META-INF/spring.factories | 2 +- ...oot.autoconfigure.AutoConfiguration.imports | 2 +- .../DynamicTableGeneratorQueryTest.java | 4 ++-- springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- 15 files changed, 33 insertions(+), 33 deletions(-) rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/{JPAQuery.java => JpaQuery.java} (99%) rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/{JPAQueryConfiguration.java => JpaQueryConfiguration.java} (50%) rename springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/{JPAQueryContextRegister.java => JpaQueryContextRegister.java} (60%) diff --git a/pom.xml b/pom.xml index 6481a056..4938e446 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.codingapi.springboot springboot-parent - 2.10.25 + 2.10.26 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 5079b2dc..0a2a24a8 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.25 + 2.10.26 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index bd965f6d..03e1f094 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 2.10.25 + 2.10.26 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQuery.java similarity index 99% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQuery.java index 3ad16091..37bc40bc 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQuery.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQuery.java @@ -13,7 +13,7 @@ import java.util.List; @AllArgsConstructor -public class JPAQuery { +public class JpaQuery { private final EntityManager entityManager; diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryConfiguration.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryConfiguration.java similarity index 50% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryConfiguration.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryConfiguration.java index 598fe0c6..81a77174 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryConfiguration.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryConfiguration.java @@ -6,16 +6,16 @@ @Configuration -public class JPAQueryConfiguration { +public class JpaQueryConfiguration { @Bean - public JPAQuery dynamicQuery(EntityManager entityManager){ - return new JPAQuery(entityManager); + public JpaQuery dynamicQuery(EntityManager entityManager){ + return new JpaQuery(entityManager); } @Bean - public JPAQueryContextRegister jpaQueryContextRegister(JPAQuery JPAQuery){ - return new JPAQueryContextRegister(JPAQuery); + public JpaQueryContextRegister jpaQueryContextRegister(JpaQuery JPAQuery){ + return new JpaQueryContextRegister(JPAQuery); } } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContext.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContext.java index e39b2d5c..e103db08 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContext.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContext.java @@ -13,10 +13,10 @@ private JpaQueryContext() { } @Getter - private JPAQuery JPAQuery; + private JpaQuery jpaQuery; - void setJPAQuery(JPAQuery JPAQuery) { - this.JPAQuery = JPAQuery; + void setJpaQuery(JpaQuery jpaQuery) { + this.jpaQuery = jpaQuery; } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryContextRegister.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContextRegister.java similarity index 60% rename from springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryContextRegister.java rename to springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContextRegister.java index b6fc7198..240bea8a 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JPAQueryContextRegister.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContextRegister.java @@ -4,13 +4,13 @@ import org.springframework.beans.factory.InitializingBean; @AllArgsConstructor -public class JPAQueryContextRegister implements InitializingBean { +public class JpaQueryContextRegister implements InitializingBean { - private JPAQuery JPAQuery; + private JpaQuery JPAQuery; @Override public void afterPropertiesSet() throws Exception { - JpaQueryContext.getInstance().setJPAQuery(JPAQuery); + JpaQueryContext.getInstance().setJpaQuery(JPAQuery); } } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java index a18667e4..77f1758d 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java @@ -14,39 +14,39 @@ public interface DynamicRepository extends BaseRepository { default List dynamicListQuery(SQLBuilder builder) { - return JpaQueryContext.getInstance().getJPAQuery().listQuery(builder); + return JpaQueryContext.getInstance().getJpaQuery().listQuery(builder); } default List dynamicListQuery(String sql, Object... params) { - return JpaQueryContext.getInstance().getJPAQuery().listQuery(getEntityClass(), sql, params); + return JpaQueryContext.getInstance().getJpaQuery().listQuery(getEntityClass(), sql, params); } default List dynamicListQuery(Class clazz, String sql, Object... params) { - return JpaQueryContext.getInstance().getJPAQuery().listQuery(clazz, sql, params); + return JpaQueryContext.getInstance().getJpaQuery().listQuery(clazz, sql, params); } default Page dynamicPageQuery(SQLBuilder builder, PageRequest request) { - return JpaQueryContext.getInstance().getJPAQuery().pageQuery(builder, request); + return JpaQueryContext.getInstance().getJpaQuery().pageQuery(builder, request); } default Page dynamicPageQuery(String sql, String countSql, PageRequest request, Object... params) { - return JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, countSql, request, params); + return JpaQueryContext.getInstance().getJpaQuery().pageQuery(getEntityClass(), sql, countSql, request, params); } default Page dynamicPageQuery(String sql, PageRequest request, Object... params) { - return JpaQueryContext.getInstance().getJPAQuery().pageQuery(getEntityClass(), sql, request, params); + return JpaQueryContext.getInstance().getJpaQuery().pageQuery(getEntityClass(), sql, request, params); } default Page dynamicPageQuery(Class clazz, String sql, String countSql, PageRequest request, Object... params) { - return JpaQueryContext.getInstance().getJPAQuery().pageQuery(clazz, sql, countSql, request, params); + return JpaQueryContext.getInstance().getJpaQuery().pageQuery(clazz, sql, countSql, request, params); } default Page dynamicMapPageQuery(QueryColumns columns, String sql, String countSql, PageRequest request, Object... params) { - return JpaQueryContext.getInstance().getJPAQuery().pageMapQuery(columns, sql, countSql, request, params); + return JpaQueryContext.getInstance().getJpaQuery().pageMapQuery(columns, sql, countSql, request, params); } default List dynamicMapListQuery(QueryColumns columns, String sql, Object... params) { - return JpaQueryContext.getInstance().getJPAQuery().listMapQuery(columns, sql, params); + return JpaQueryContext.getInstance().getJpaQuery().listMapQuery(columns, sql, params); } } diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRuntime.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRuntime.java index 2b5a63ba..ef33effc 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRuntime.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/ScriptRuntime.java @@ -2,7 +2,7 @@ import com.codingapi.springboot.fast.jdbc.JdbcQuery; import com.codingapi.springboot.fast.jdbc.JdbcQueryContext; -import com.codingapi.springboot.fast.jpa.JPAQuery; +import com.codingapi.springboot.fast.jpa.JpaQuery; import com.codingapi.springboot.fast.jpa.JpaQueryContext; import groovy.lang.Binding; import groovy.lang.GroovyShell; @@ -18,7 +18,7 @@ static Object running(String script) { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); ScriptRequest request = new ScriptRequest(attributes.getRequest()); JdbcQuery jdbcQuery = JdbcQueryContext.getInstance().getJdbcQuery(); - JPAQuery jpaQuery = JpaQueryContext.getInstance().getJPAQuery(); + JpaQuery jpaQuery = JpaQueryContext.getInstance().getJpaQuery(); binding.setVariable("$request", request); binding.setVariable("$jpa", jpaQuery); diff --git a/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories b/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories index f2d11256..25372a67 100644 --- a/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories +++ b/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories @@ -1,4 +1,4 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.codingapi.springboot.fast.DataFastConfiguration,\ -com.codingapi.springboot.fast.jpa.JPAQueryConfiguration,\ +com.codingapi.springboot.fast.jpa.JpaQueryConfiguration,\ com.codingapi.springboot.fast.jdbc.JdbcQueryConfiguration \ No newline at end of file diff --git a/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 68b400af..526c33d9 100644 --- a/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/springboot-starter-data-fast/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,3 +1,3 @@ com.codingapi.springboot.fast.DataFastConfiguration -com.codingapi.springboot.fast.jpa.JPAQueryConfiguration +com.codingapi.springboot.fast.jpa.JpaQueryConfiguration com.codingapi.springboot.fast.jdbc.JdbcQueryConfiguration \ No newline at end of file diff --git a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorQueryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorQueryTest.java index 4d4dd64b..be662719 100644 --- a/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorQueryTest.java +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorQueryTest.java @@ -2,7 +2,7 @@ import com.codingapi.springboot.fast.jdbc.JdbcQuery; import com.codingapi.springboot.fast.jdbc.JdbcQueryContext; -import com.codingapi.springboot.fast.jpa.JPAQuery; +import com.codingapi.springboot.fast.jpa.JpaQuery; import com.codingapi.springboot.fast.jpa.JpaQueryContext; import com.codingapi.springboot.fast.metadata.TableEntityMetadata; import javax.persistence.EntityManagerFactory; @@ -53,7 +53,7 @@ void generateThenUpdateQuery() throws ClassNotFoundException { dynamicTableGenerator.generateMigratorTableDDL(entityClass, true); // 通过DynamicTableGenerator 动态创建的entity无法通过jpa的 EntityManager进行数据查询处理, 因为Entity不在JPA扫描支持的范围内。 - JPAQuery jpaQuery = JpaQueryContext.getInstance().getJPAQuery(); + JpaQuery jpaQuery = JpaQueryContext.getInstance().getJpaQuery(); assertThrows(Exception.class,()->{ jpaQuery.listQuery(entityClass,"select t from com.codingapi.springboot.fast.entity.Test"); }); diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 5ca5cd4e..dc962171 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.25 + 2.10.26 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 9f16cb54..24220084 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 2.10.25 + 2.10.26 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index 2e982604..67b7a608 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 2.10.25 + 2.10.26 springboot-starter