diff --git a/README.md b/README.md index 149c9aa5..74f5fe9a 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,18 @@ 本框架基于springboot为提供领域驱动设计与事件风暴开发落地,提供的范式开源框架。 +## Project Version | 项目版本说明 + +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-id-generator | Id自增策略框架 -* springboot-starter-security-jwt | security&jwt权限框架 +* springboot-starter-data-authorization | 数据权限框架 +* springboot-starter-flow | 流程引擎框架 +* springboot-starter-security | security权限框架支持基于JWT的无状态权限认证与Redis的有状态权限认证 ## SpringBoot DDD Architecture | SpringBoot DDD 框架图 @@ -37,17 +43,24 @@ ${last.version} - - + + + com.codingapi.springboot + springboot-starter-data-authorization + ${last.version} + + + + com.codingapi.springboot - springboot-starter-id-generator + springboot-starter-flow ${last.version} com.codingapi.springboot - springboot-starter-security-jwt + springboot-starter-security ${last.version} @@ -66,7 +79,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 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 diff --git a/docs/wiki/springboot-starter-data-fast.md b/docs/wiki/springboot-starter-data-fast.md index 0466431d..aa35baca 100644 --- a/docs/wiki/springboot-starter-data-fast.md +++ b/docs/wiki/springboot-starter-data-fast.md @@ -2,46 +2,240 @@ springboot-starter-data-fast 基于JPA的快速API能力服务 +## FastRepository 的使用教程 + +继承FastRepository接口,实现自定义的接口,即可使用FastRepository的能力 ```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 { +import com.codingapi.springboot.fast.entity.Demo; +import com.codingapi.springboot.fast.query.FastRepository; + +public interface DemoRepository extends FastRepository { + +} + + +``` +动态FastRepository的能力展示 + +``` + + // 重写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 pageRequest1() { + 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%"); + //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查询 + @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()); + } - @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); + // 动态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); - @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); + 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()); + } + +``` + +## ScriptMapping 教程 + +通过动态添加mvc mapping实现查询功能. + + +``` +ScriptMapping scriptMapping = new ScriptMapping({mapinggUrl}, {mapinggMethod}, {mappingGrovvry}); +scriptMappingRegister.addMapping(scriptMapping); + +``` +mapinggUrl 是mvc接口的地址 +mapinggMethod 是mvc接口的请求方式 +mappingGrovvry 是执行的查询脚本 + +脚本实例代码: +* 动态分页查询 +``` +// 获取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()); +``` +脚本语法介绍: +* $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 ``` -@FastController 用于标记当前接口为Fast接口 -@FastMapping 用于标记当前接口的映射关系 -mapping为接口映射路径,method为接口请求方法 -value为查询语句,countQuery为查询总数语句,query为查询参数,支持分页查询,排序查询,查询参数等等 -MultiResponse为返回结果 -@PreAuthorize(value = "hasRole('ROLE_USER')") 用于标记当前接口的权限,如果不需要权限可以不用添加 +// 查询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/docs/wiki/springboot-starter-security-jwt.md b/docs/wiki/springboot-starter-security.md similarity index 61% rename from docs/wiki/springboot-starter-security-jwt.md rename to docs/wiki/springboot-starter-security.md index dd984683..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/** @@ -51,14 +61,22 @@ security默认的账户密码为admin/admin,可以通过重写UserDetailsServi 也可以通过数据库账户获取账户数据,请自己实现UserDetailsService接口 ## 登录拦截 -可以通过重写SecurityLoginHandler来实现自定义登录拦截 -```java +可以通过重写SecurityLoginHandler来实现自定义登录拦截,preHandle登录前的拦截处理,postHandle登录后的拦截处理 +``` @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) { + + } + }; +} ``` ## 获取当前用户 @@ -66,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/event.md b/event.md new file mode 100644 index 00000000..d632f4a7 --- /dev/null +++ b/event.md @@ -0,0 +1,38 @@ +# 流程事件触发机制 + +* 发起流程 +事件: CREATE TODO SAVE +* 保存流程 +事件: SAVE +* 提交流程 +事件: PASS TODO(下一个节点记录数据) +* 驳回流程 +事件: REJECT TODO(下一个节点记录数据) +* 撤回流程 +事件: RECALL +* 删除流程 +事件: DELETE +* 作废流程 +事件: VOIDED +* 退回流程 +事件:BACK +* 流程结束 +事件: FINISH +* 转办流程 +事件:TRANSFER TODO(下一个节点记录数据) +* 唤醒流程 +事件: TODO +* 催办流程 +事件: URGE 当前审批人 +* 延期流程 +事件: 未发送事件 +* 停止流程 +事件: STOP 当前审批人 + +--------------------- +自定义事件:是前端自己触法的逻辑 +自定义接口:是执行后端按钮配置的脚本 + +在开始节点点击任何按钮的时候,若流程不存在则会先执行流程的创建,然后再执行对应的按钮操作。 + + diff --git a/pom.xml b/pom.xml index 3ba9ed9b..4938e446 100644 --- a/pom.xml +++ b/pom.xml @@ -3,43 +3,52 @@ 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 - 3.1.2 + 2.7.18 com.codingapi.springboot springboot-parent - 2.1.11 + 2.10.26 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 - 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.53 + 0.12.6 + 2.17.0 + 3.17.0 + 1.8.1 + 1.12.0 0.10.2 0.9.16 - 1.70 + 1.79 1.2.0 - 2.0 + 2.2 + 4.0.24 + 2.3.232 + 5.6.2 + 5.0 @@ -72,10 +81,22 @@ + + com.esotericsoftware + kryo + ${esotericsoftware.kryo.version} + + + + com.h2database + h2 + ${h2.version} + + org.bouncycastle - bcprov-jdk15on - ${bcprov-jdk15on.version} + bcprov-jdk18on + ${bcprov-jdk18on.version} @@ -90,6 +111,18 @@ ${commons-crypto.version} + + commons-io + commons-io + ${commons-io.version} + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + org.perf4j perf4j @@ -134,7 +167,7 @@ com.codingapi.springboot - springboot-starter-security-jwt + springboot-starter-security ${codingapi.framework.version} @@ -156,6 +189,36 @@ ${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} + + + + com.github.jsqlparser + jsqlparser + ${jsqlparser.version} + + @@ -172,6 +235,20 @@ -Xlint:deprecation + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + + ${project.version} + ${project.name} + + + + @@ -216,9 +293,10 @@ springboot-starter - springboot-starter-security-jwt + springboot-starter-security + springboot-starter-data-authorization springboot-starter-data-fast - springboot-starter-id-generator + springboot-starter-flow @@ -228,9 +306,10 @@ springboot-starter - springboot-starter-security-jwt + springboot-starter-security + springboot-starter-data-authorization springboot-starter-data-fast - springboot-starter-id-generator + springboot-starter-flow @@ -238,7 +317,7 @@ org.jacoco jacoco-maven-plugin - 0.8.9 + 0.8.12 @@ -258,7 +337,7 @@ org.openclover clover-maven-plugin - 4.4.1 + 4.5.2 true true @@ -271,6 +350,7 @@ + @@ -278,27 +358,15 @@ springboot-starter - springboot-starter-security-jwt + springboot-starter-security + springboot-starter-data-authorization springboot-starter-data-fast - springboot-starter-id-generator + springboot-starter-flow - - - - 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 @@ -312,20 +380,18 @@ - - 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 @@ -344,7 +410,6 @@ - org.apache.maven.plugins maven-gpg-plugin @@ -363,8 +428,6 @@ - - diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml new file mode 100644 index 00000000..0a2a24a8 --- /dev/null +++ b/springboot-starter-data-authorization/pom.xml @@ -0,0 +1,78 @@ + + + 4.0.0 + + springboot-parent + com.codingapi.springboot + 2.10.26 + + + springboot-starter-data-authorization + 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..3915d39b --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/enhancer/DataPermissionSQLEnhancer.java @@ -0,0 +1,167 @@ +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.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; +import net.sf.jsqlparser.statement.select.*; + +import java.sql.SQLException; +import java.util.List; + +/** + * 数据权限 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; + this.deepMatch(select); + return statement.toString(); + } + } catch (Exception e) { + throw new SQLException(e); + } + 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); + } + } + } + + + // 增强 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..47bb18bf --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/DefaultSQLInterceptor.java @@ -0,0 +1,40 @@ +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(exception!=null){ + log.error("sql:{}",sql); + log.error("newSql:{}",newSql); + log.error(exception.getMessage(),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..c22d4e25 --- /dev/null +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/interceptor/SQLRunningContext.java @@ -0,0 +1,83 @@ +package com.codingapi.springboot.authorization.interceptor; + +import lombok.Getter; + +import java.sql.SQLException; +import java.util.function.Supplier; + +/** + * 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(Supplier supplier) { + try { + skipInterceptor.set(true); + return (T) supplier.get(); + } finally { + skipInterceptor.set(false); + } + } + + + /** + * 跳过数据权限拦截 + * + * @param runnable 业务逻辑 + */ + public void skipDataAuthorization(Runnable runnable) { + try { + skipInterceptor.set(true); + runnable.run(); + } 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..70fa0f8a --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/DataAuthorizationContextTest.java @@ -0,0 +1,341 @@ +package com.codingapi.springboot.authorization; + +import com.codingapi.springboot.authorization.current.CurrentUser; +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.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 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.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 { + + 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) { + String conditionTemplate = "%s.id > -100 "; + return Condition.formatCondition(conditionTemplate, 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) { + if ("t_depart".equalsIgnoreCase(tableName)) { + return true; + } + return false; + } + + @Override + public boolean supportRowAuthorization(String tableName, String tableAlias) { + if ("t_depart".equalsIgnoreCase(tableName)) { + return true; + } + return false; + } + }); + + 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..008062a5 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/java/com/codingapi/springboot/authorization/analyzer/SelectSQLAnalyzerTest.java @@ -0,0 +1,225 @@ +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());; + } + + + @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-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..f5ac2519 --- /dev/null +++ b/springboot-starter-data-authorization/src/test/resources/application.properties @@ -0,0 +1,15 @@ + +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 + +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 141c3862..03e1f094 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,19 +5,26 @@ springboot-parent com.codingapi.springboot - 2.1.11 + 2.10.26 4.0.0 + springboot-starter-data-fast springboot-starter-data-fast + springboot-starter-data-fast project for Spring Boot - 17 + 8 + + net.bytebuddy + byte-buddy + + org.springframework.boot spring-boot-starter-web @@ -28,6 +35,12 @@ springboot-starter + + jakarta.servlet + jakarta.servlet-api + provided + + org.springframework.boot spring-boot-starter-data-jpa @@ -39,6 +52,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 0dcf4268..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,10 +1,9 @@ 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.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; @@ -12,8 +11,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; -import jakarta.persistence.EntityManager; -import java.util.List; +import javax.persistence.EntityManager; @Configuration @ConditionalOnClass(WebMvcConfigurer.class) @@ -22,28 +20,21 @@ public class DataFastConfiguration { @Bean @ConditionalOnMissingBean - public MvcEndpointMapping mvcEndpointMapping(RequestMappingHandlerMapping handlerMapping) { - return new MvcEndpointMapping(handlerMapping); + public FastMvcMappingRegister mvcMappingRegister(@Qualifier("requestMappingHandlerMapping") RequestMappingHandlerMapping handlerMapping) { + return new FastMvcMappingRegister(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 FastScriptMappingRegister scriptMappingRegister(FastMvcMappingRegister fastMvcMappingRegister) { + return new FastScriptMappingRegister(fastMvcMappingRegister); } } 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/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/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 04067091..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 jakarta.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 dbc4e118..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 jakarta.persistence.EntityManager; -import jakarta.persistence.Parameter; -import jakarta.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/generator/DynamicTableGenerator.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/generator/DynamicTableGenerator.java new file mode 100644 index 00000000..91231ab8 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/generator/DynamicTableGenerator.java @@ -0,0 +1,251 @@ +package com.codingapi.springboot.fast.generator; + +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.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.*; + +/** + * DynamicTableGenerator 数据库表动态构建器 + */ +public class DynamicTableGenerator { + + /** + * 数据库方言 + */ + private final Class dialect; + private final StandardServiceRegistry serviceRegistry; + private final SchemaManagementTool managementTool; + + public DynamicTableGenerator(Class dialectClass, String jdbcUrl) { + this(dialectClass,jdbcUrl,null,null); + } + + public DynamicTableGenerator(Class dialectClass, String jdbcUrl, String username, String password) { + this.dialect = dialectClass; + StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder() + .applySetting(AvailableSettings.DIALECT, dialect.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.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<>(); + private final boolean executable; + + public TargetDescriptorImpl(boolean executable) { + this.executable = executable; + } + + @Override + public EnumSet getTargetTypes() { + EnumSet targetTypes = EnumSet.of(TargetType.SCRIPT); + if(executable) { + // 在数据库中执行 + targetTypes.add(TargetType.DATABASE); + } + return targetTypes; + } + + @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); + } + } + + /** + * 创建删除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(executable); + + managementTool.getSchemaDropper(Collections.emptyMap()).doDrop(metadata, + new ExecutionOptionsImpl(), + new SourceDescriptorImpl(), + targetDescriptor); + + 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(executable); + + managementTool.getSchemaCreator(Collections.emptyMap()).doCreation(metadata, + new ExecutionOptionsImpl(), + new SourceDescriptorImpl(), + targetDescriptor); + 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(executable); + + managementTool.getSchemaMigrator(Collections.emptyMap()).doMigration(metadata, + new ExecutionOptionsImpl(), + targetDescriptor); + return targetDescriptor.getDDL(); + } + + /** + * 检验对象与数据库是否一致,一致时无异常信息 + * @param entityClass entity class对象 + * @return 异常列表 + */ + 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/jdbc/JdbcQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java new file mode 100644 index 00000000..b28743d4 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jdbc/JdbcQuery.java @@ -0,0 +1,97 @@ +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; +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> queryForMapList(SQLBuilder builder) { + return queryForMapList(builder.getSQL(), builder.getParams()); + } + + public List> queryForMapList(String sql, Object... params) { + return jdbcTemplate.query(sql, new CamelCaseRowMapper(), params); + } + + 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, new BeanPropertyRowMapper<>(clazz), params); + } + + 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, 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; + return this.queryForPage(sql, countSql, clazz, pageRequest, 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, 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; + return this.queryForMapPage(sql, countSql, pageRequest, params); + } + + + 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, Long.class, newParams); + } +} 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/jpa/JpaQuery.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQuery.java new file mode 100644 index 00000000..37bc40bc --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQuery.java @@ -0,0 +1,80 @@ +package com.codingapi.springboot.fast.jpa; + +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; +import org.springframework.data.domain.PageRequest; + +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import java.util.List; + +@AllArgsConstructor +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) { + for (int i = 0; i < params.length; i++) { + query.setParameter(i + 1, params[i]); + } + } + 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); + } + + 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(); + } + + 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 = 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/JpaQueryConfiguration.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryConfiguration.java new file mode 100644 index 00000000..81a77174 --- /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/JpaQueryContext.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContext.java new file mode 100644 index 00000000..e103db08 --- /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/jpa/JpaQueryContextRegister.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/JpaQueryContextRegister.java new file mode 100644 index 00000000..240bea8a --- /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/SQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java new file mode 100644 index 00000000..2639d614 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java @@ -0,0 +1,80 @@ +package com.codingapi.springboot.fast.jpa; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +public class SQLBuilder { + + private final StringBuilder querySqlBuilder; + private final StringBuilder countSQLBuilder; + @Getter + 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(String sql,String countSql) { + this(null, sql, 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.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) { + querySqlBuilder.append(" ").append(sql).append(index).append(" "); + countSQLBuilder.append(" ").append(sql).append(index).append(" "); + params.add(value); + index++; + } + } + + 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){ + querySqlBuilder.append(" ").append(sql).append(" "); + countSQLBuilder.append(" ").append(sql).append(" "); + } + + public String getSQL() { + return querySqlBuilder.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/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/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..3adf3854 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicNativeRepository.java @@ -0,0 +1,67 @@ +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; + +import java.util.List; +import java.util.Map; + +@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().queryForMapList(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 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); + } + + 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 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> 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 new file mode 100644 index 00000000..77f1758d --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicRepository.java @@ -0,0 +1,52 @@ +package com.codingapi.springboot.fast.jpa.repository; + +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; + +import java.util.List; + +@NoRepositoryBean +public interface DynamicRepository extends BaseRepository { + + default List dynamicListQuery(SQLBuilder builder) { + return JpaQueryContext.getInstance().getJpaQuery().listQuery(builder); + } + + default List dynamicListQuery(String sql, Object... 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); + } + + 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 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); + } + + default Page dynamicPageQuery(Class clazz, String sql, String countSql, PageRequest request, Object... 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 JpaQueryContext.getInstance().getJpaQuery().listMapQuery(columns, sql, params); + } + +} 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 new file mode 100644 index 00000000..cc496f48 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/DynamicSQLBuilder.java @@ -0,0 +1,190 @@ +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 lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Sort; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 动态条件查询组装 + */ +@Slf4j +class DynamicSQLBuilder { + + private final PageRequest request; + + 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.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(); + } + + 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, querySQL); + if (i != filters.size() - 1) { + querySQL.append(" AND "); + } + } + } + + Sort sort = request.getSort(); + if (sort.isSorted()) { + orderSQL.append(" ORDER BY "); + List orders = sort.toList(); + for (int i = 0; i < orders.size(); i++) { + Sort.Order order = orders.get(i); + orderSQL.append(order.getProperty()).append(" ").append(order.getDirection().name()); + if (i != orders.size() - 1) { + orderSQL.append(","); + } + } + } + + this.hql.append(querySQL); + this.hql.append(orderSQL); + this.countHql.append(querySQL); + + log.debug("hql:{}", hql); + log.debug("params:{}", params); + + } + + + 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.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]); + paramIndex++; + } + + if (filter.isLike()) { + hql.append(filter.getKey()).append(" LIKE ?").append(paramIndex); + 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())); + 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]); + 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(); + } + +} diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleBuilder.java new file mode 100644 index 00000000..6b72dec3 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/ExampleBuilder.java @@ -0,0 +1,49 @@ +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; + +/** + * Example组装 + */ +class ExampleBuilder { + + private final PageRequest request; + private final Class clazz; + + public ExampleBuilder(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 new file mode 100644 index 00000000..0a62bf7e --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/FastRepository.java @@ -0,0 +1,43 @@ +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.data.domain.Page; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.repository.NoRepositoryBean; + +/** + * 更强大的Repository对象 + * + * @param + * @param + */ +@NoRepositoryBean +public interface FastRepository extends JpaRepository, JpaSpecificationExecutor, DynamicRepository, DynamicNativeRepository { + + default Page findAll(PageRequest request) { + if (request.hasFilter()) { + Class clazz = getEntityClass(); + ExampleBuilder exampleBuilder = new ExampleBuilder(request, clazz); + return findAll(exampleBuilder.getExample(), request); + } + return findAll((org.springframework.data.domain.PageRequest) request); + } + + default Page pageRequest(PageRequest request) { + if (request.hasFilter()) { + Class clazz = getEntityClass(); + DynamicSQLBuilder dynamicSQLBuilder = new DynamicSQLBuilder(request, clazz); + return dynamicPageQuery(dynamicSQLBuilder.getHQL(),dynamicSQLBuilder.getCountHQL(), request, dynamicSQLBuilder.getParams()); + } + return findAll((org.springframework.data.domain.PageRequest) request); + } + + + default Page searchRequest(SearchRequest request) { + Class clazz = getEntityClass(); + return pageRequest(request.toPageRequest(clazz)); + } + +} 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..a47a0650 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/repository/SortRepository.java @@ -0,0 +1,39 @@ +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 = Integer.MAX_VALUE; + for (Object objectId : request.getIds()) { + ID id = (ID) objectId; + T t = getReferenceById(id); + if (t.getSort() == null) { + minSort = 0; + } else { + if (t.getSort() < minSort) { + minSort = t.getSort(); + } + } + list.add(t); + } + for (T t : list) { + t.setSort(minSort++); + } + saveAll(list); + } + } + + +} 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..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,6 +1,6 @@ package com.codingapi.springboot.fast.manager; -import jakarta.persistence.EntityManager; +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 ea87bea4..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,6 +1,6 @@ package com.codingapi.springboot.fast.manager; -import jakarta.persistence.EntityManager; +import javax.persistence.EntityManager; import lombok.AllArgsConstructor; import org.springframework.beans.factory.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/FastMvcMappingRegister.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/FastMvcMappingRegister.java index cf2eff3b..35d95f1e 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/FastMvcMappingRegister.java @@ -10,10 +10,11 @@ import java.lang.reflect.Method; @AllArgsConstructor -public class MvcEndpointMapping { +public class FastMvcMappingRegister { 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/metadata/TableEntityClassBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/TableEntityClassBuilder.java new file mode 100644 index 00000000..48bf3d35 --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/metadata/TableEntityClassBuilder.java @@ -0,0 +1,216 @@ +package com.codingapi.springboot.fast.metadata; + +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; +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 java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 动态实体构建器 - 基于 TableEntityMetadata 元数据 + */ +class TableEntityClassBuilder { + + 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 { + this.buildColumns(); + Class clazz = builder.make() + .load(TableEntityClassBuilder.class.getClassLoader(), + ClassLoadingStrategy.Default.WRAPPER) + .getLoaded(); + DynamicTableClassLoader.getInstance().registerClass(clazz); + return clazz; + + } catch (Exception e) { + throw new RuntimeException("Failed to build dynamic entity: " + + metadata.getClassName(), e); + } + } + + + private void buildColumns() { + for (TableEntityMetadata.ColumnMeta column : metadata.getColumns()) { + this.addColumnField(column); + } + } + + + /** + * 构建实体类注解 + */ + private AnnotationDescription[] buildEntityAnnotations() { + List annotations = new ArrayList<>(); + + // @Entity 注解 + annotations.add(AnnotationDescription.Builder.ofType(Entity.class).build()); + + // @Table 注解 + if (metadata.getTable() != null) { + AnnotationDescription.Builder tableBuilder = + AnnotationDescription.Builder.ofType(Table.class); + + TableEntityMetadata.TableMeta tableMeta = metadata.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 (metadata.getTable() != null && StringUtils.hasText(metadata.getTable().getComment())) { + AnnotationDescription.Builder commentBuilder = + AnnotationDescription.Builder.ofType(Comment.class); + + TableEntityMetadata.TableMeta tableMeta = metadata.getTable(); + commentBuilder = commentBuilder.define("value", tableMeta.getComment()); + annotations.add(commentBuilder.build()); + } + + return annotations.toArray(new AnnotationDescription[0]); + } + + /** + * 添加字段 + */ + private void addColumnField(TableEntityMetadata.ColumnMeta columnMeta) { + // 确定字段类型 + Class fieldType = columnMeta.getType(); + + // 构建字段名 + String fieldName = columnMeta.getFieldName(); + + // 构建字段注解 + List fieldAnnotations = this.buildFieldAnnotations(columnMeta); + + if (fieldAnnotations.isEmpty()) { + builder = builder.defineField(fieldName, fieldType, Visibility.PRIVATE); + } else { + builder = builder.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; + } + + builder = builder.defineMethod(getterName, fieldType, Visibility.PUBLIC) + .intercept(FieldAccessor.ofField(fieldName)); + + builder = builder.defineMethod(setterName, void.class, Visibility.PUBLIC) + .withParameter(fieldType) + .intercept(FieldAccessor.ofField(fieldName)); + + } + + /** + * 构建字段注解 + */ + private List buildFieldAnnotations( + TableEntityMetadata.ColumnMeta columnMeta) { + List annotations = new ArrayList<>(); + + // @Id 注解 + if (columnMeta.isPrimaryKey()) { + annotations.add(AnnotationDescription.Builder.ofType(Id.class).build()); + + // @GeneratedValue 注解 + if (columnMeta.getGeneratedValue() != null) { + TableEntityMetadata.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.getColumnName()) + .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; + } + + + private 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/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/main/java/com/codingapi/springboot/fast/query/FastRepository.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java deleted file mode 100644 index 71eeb9ae..00000000 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/query/FastRepository.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.codingapi.springboot.fast.query; - -import com.codingapi.springboot.framework.dto.request.PageRequest; -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; -import org.springframework.data.repository.NoRepositoryBean; - -@NoRepositoryBean -public interface FastRepository extends JpaRepository, JpaSpecificationExecutor { - - default Page findAll(PageRequest request){ - if(request.hasFilter()){ - Class clazz = getDomainClass(); - return findAll(request.getExample(clazz),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(); - } - -} 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/FastScriptMappingRegister.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/FastScriptMappingRegister.java new file mode 100644 index 00000000..9dc8583f --- /dev/null +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/script/FastScriptMappingRegister.java @@ -0,0 +1,46 @@ +package com.codingapi.springboot.fast.script; + +import com.codingapi.springboot.fast.mapping.FastMvcMappingRegister; +import com.codingapi.springboot.framework.dto.response.Response; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class FastScriptMappingRegister { + + private final FastMvcMappingRegister 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/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/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..ef33effc --- /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/resources/META-INF/spring.factories b/springboot-starter-data-fast/src/main/resources/META-INF/spring.factories index 545e7ce2..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,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.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 c1debcb6..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,2 +1,3 @@ com.codingapi.springboot.fast.DataFastConfiguration -com.codingapi.springboot.fast.registrar.DataFastBeanDefinitionRegistrar \ 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 283fd318..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 @@ -1,17 +1,24 @@ 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; +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 java.util.List; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +@Slf4j @SpringBootTest public class DemoRepositoryTest { @@ -20,17 +27,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 +50,72 @@ 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 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 sort(){ + 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() { demoRepository.deleteAll(); Demo demo1 = new Demo(); demo1.setName("123"); @@ -64,10 +128,165 @@ void sort(){ PageRequest request = new PageRequest(); request.setCurrent(1); request.setPageSize(10); + request.addFilter("name", Relation.LIKE, "%2%"); + + Page page = demoRepository.pageRequest(request); + assertEquals(1, page.getTotalElements()); + } + + + @Test + void customInSearch() { + 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.IN, 1, 2, 3); + + Page page = demoRepository.pageRequest(request); + System.out.println(page.getContent()); + } + + + @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()); + } + + + @Test + void customOrSearch() { + 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(0); + request.setPageSize(10); + + +// 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.findAll(request); - assertEquals(page.getContent().get(0).getName(),"456"); + + + + Page page = demoRepository.pageRequest(request); + log.info("demo:{}", page.getContent()); +// assertEquals(2, 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); + + 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()); + } + + + @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); + + 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()); + } + + + @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(0); + 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()); } + } 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()); + } + +} 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/UserRepositoryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/UserRepositoryTest.java new file mode 100644 index 00000000..8c25bb4b --- /dev/null +++ b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/UserRepositoryTest.java @@ -0,0 +1,140 @@ +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.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; +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 java.util.List; + +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 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() { + + 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 3e9e66d8..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 @@ -2,12 +2,14 @@ import lombok.Getter; import lombok.Setter; +import lombok.ToString; -import jakarta.persistence.*; +import javax.persistence.*; @Setter @Getter @Entity +@ToString @Table(name = "t_demo") public class Demo { @Id @@ -15,4 +17,6 @@ public class Demo { private Integer id; private String name; + + private Integer sort; } 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/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/generator/DynamicTableGeneratorQueryTest.java b/springboot-starter-data-fast/src/test/java/com/codingapi/springboot/fast/generator/DynamicTableGeneratorQueryTest.java new file mode 100644 index 00000000..be662719 --- /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 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-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 43b36280..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,8 +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.jpa.repository.FastRepository; -public interface DemoRepository extends FastRepository { +public interface DemoRepository extends FastRepository { } 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-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 { + + +} 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-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-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..dc962171 --- /dev/null +++ b/springboot-starter-flow/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + springboot-parent + com.codingapi.springboot + 2.10.26 + + + 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/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 new file mode 100644 index 00000000..5c152799 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/bind/IBindData.java @@ -0,0 +1,47 @@ +package com.codingapi.springboot.flow.bind; + +import com.alibaba.fastjson.JSONObject; + +/** + * 数据绑定接口 + */ +public interface IBindData { + + String CLASS_NAME_KEY = "clazzName"; + + /** + * 数据快照 + * + * @return 数据快照 + */ + default String toJsonSnapshot() { + return JSONObject.toJSONString(this); + } + + + /** + * 获取类名称 + * + * @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/build/FlowWorkBuilder.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java new file mode 100644 index 00000000..e8a07925 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java @@ -0,0 +1,153 @@ +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; +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; + +import java.util.List; + +/** + * 流程工作构建器 + */ +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 skipIfSameApprover(boolean skipIfSameApprover) { + this.work.setSkipIfSameApprover(skipIfSameApprover); + 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, 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,false, null); + } + + 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,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,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,false, buttons); + } + + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher) { + 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,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,boolean mergeable) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable,mergeable, null); + } + + + 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..09217db6 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java @@ -0,0 +1,98 @@ +package com.codingapi.springboot.flow.build; + +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; +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"); + boolean mergeable = properties.getBoolean("mergeable"); + 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"); + 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,mergeable, buttons); + 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 < edges.size(); i++) { + JSONObject edge = edges.getJSONObject(i); + String id = edge.getString("id"); + String sourceNodeId = edge.getString("sourceNodeId"); + String targetNodeId = edge.getString("targetNodeId"); + + JSONObject properties = edge.getJSONObject("properties"); + String name = properties.containsKey("name") ? properties.getString("name") : null; + String outTrigger = properties.containsKey("outTrigger") ? properties.getString("outTrigger") : OutTrigger.defaultOutTrigger().getScript(); + boolean back = properties.containsKey("back") ? properties.getBoolean("back") : false; + int order = properties.containsKey("order") ? properties.getIntValue("order") : 1; + + FlowNode source = getFlowNodeById(sourceNodeId); + FlowNode target = getFlowNodeById(targetNodeId); + + FlowRelation relation = new FlowRelation(id, name, source, target, new OutTrigger(outTrigger), order, back); + flowRelations.add(relation); + } + } +} 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 new file mode 100644 index 00000000..90b08007 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSession.java @@ -0,0 +1,302 @@ +package com.codingapi.springboot.flow.content; + +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.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; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.Getter; + +import java.util.List; + +/** + * 流程groovy脚本回话对象 + */ +@Getter +public class FlowSession { + + // 当前的流程记录(当前审批的流程) + private final FlowRecord flowRecord; + // 当前的流程设计器 + private final FlowWork flowWork; + // 当前的流程节点 + private final FlowNode flowNode; + // 流程的创建者 + private final IFlowOperator createOperator; + // 当前的操作者(当前的操作者,非代办人) + private final IFlowOperator currentOperator; + // 流程绑定数据 + private final IBindData bindData; + // 流程审批意见 + private final Opinion opinion; + // 当前节点的审批记录 + private final List historyRecords; + // bean提供者 + private final FlowSessionBeanProvider provider; + + 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; + 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); + } + + + public T getBean(Class clazz) { + return provider.getBean(clazz); + } + + + /** + * 获取审批意见 + */ + public String getAdvice() { + if (opinion != null) { + return opinion.getAdvice(); + } else { + return null; + } + } + + /** + * 创建节点结果 + * + * @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); + } + + /** + * 创建流程提醒 + * + * @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 void stopFlow() { + if (flowRecord == null) { + throw new IllegalArgumentException("flow record is null"); + } + FlowService flowService = loadFlowService(); + flowService.stop(flowRecord.getId(), currentOperator); + } + + /** + * 上级节点的状态是驳回状态 + * + * @return 上级节点的状态是驳回状态 + */ + public boolean backStateIsReject() { + if (flowRecord == null) { + return false; + } + 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; + } + + /** + * 上级节点的状态是驳回状态 + * + * @see #backStateIsReject() + */ + @Deprecated + public boolean isRejectState() { + return this.backStateIsReject(); + } + + /** + * 当前节点的状态是驳回状态 + */ + public boolean currentStateIsReject() { + if (flowRecord != null) { + return flowRecord.getFlowSourceDirection() == FlowSourceDirection.REJECT; + } + return false; + } + + + /** + * 预提交流程 + */ + 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); + } + + + /** + * 撤回流程 + * @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/content/FlowSessionBeanProvider.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSessionBeanProvider.java new file mode 100644 index 00000000..06731b8c --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/content/FlowSessionBeanProvider.java @@ -0,0 +1,37 @@ +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; + } + + 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/domain/FlowButton.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowButton.java new file mode 100644 index 00000000..7dd5d8e5 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowButton.java @@ -0,0 +1,84 @@ +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 String eventKey; + + /** + * 排序 + */ + 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 new file mode 100644 index 00000000..fcad0edd --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java @@ -0,0 +1,357 @@ +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.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; +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.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 流程节点 + */ +@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; + + /** + * 是否合并记录 + *

+ * 如果为true,则表示该节点可以合并记录 + */ + private boolean mergeable; + + + /** + * 创建时间 + */ + private long createTime; + /** + * 更新时间 + */ + private long updateTime; + + /** + * 超时时间(毫秒) + */ + private long timeout; + + /** + * 异常触发器,当流程发生异常时异常通常是指找不到审批人,将会触发异常触发器,异常触发器可以是一个节点 + */ + @Setter + private ErrTrigger errTrigger; + + /** + * 流程节点按钮 + */ + 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() { + 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.mergeable, + this.createTime, + this.updateTime, + this.timeout, + this.errTrigger == null ? null : this.errTrigger.getScript(), + this.buttons + ); + } + + + public FlowNode(String id, + String name, + String code, + String view, + NodeType type, + ApprovalType approvalType, + TitleGenerator titleGenerator, + OperatorMatcher operatorMatcher, + long timeout, + ErrTrigger errTrigger, + boolean editable, + boolean mergeable, + List buttons) { + 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; + this.mergeable = mergeable; + this.buttons = buttons; + } + + + /** + * 加载节点的操作者 + * + * @param flowSession 操作内容 + * @return 是否匹配 + */ + public List loadFlowNodeOperator(FlowSession flowSession, FlowOperatorRepository flowOperatorRepository) { + return flowOperatorRepository.findByIds(this.operatorMatcher.matcher(flowSession)); + } + + + /** + * 创建流程记录 + * + * @param workId 流程设计id + * @param workCode 流程设计编码 + * @param processId 流程id + * @param preId 上一条流程记录id + * @param title 流程标题 + * @param createOperator 流程操作者 + * @param currentOperator 当前操作者 + * @param snapshot 快照数据 + * @return 流程记录 + */ + public FlowRecord createRecord(long workId, + String workCode, + String processId, + long preId, + String title, + IFlowOperator createOperator, + IFlowOperator currentOperator, + BindDataSnapshot snapshot, + boolean isWaiting) { + + // 当前操作者存在委托人时,才需要寻找委托人 + IFlowOperator flowOperator = currentOperator; + while (flowOperator.entrustOperator() != null) { + //寻找委托人 + flowOperator = flowOperator.entrustOperator(); + } + 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); + 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(isWaiting?FlowType.WAITING: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); + } + + /** + * 是否传阅节点 + */ + 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/FlowRelation.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowRelation.java new file mode 100644 index 00000000..16f7df4f --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowRelation.java @@ -0,0 +1,171 @@ +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 { + + + public static final int DEFAULT_ORDER = -100; + + /** + * 关系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..05a6ca3c --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowWork.java @@ -0,0 +1,343 @@ +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; + + /** + * 是否跳过相同审批人,默认为false + */ + @Setter + private boolean skipIfSameApprover; + + /** + * 最大延期次数 + */ + @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.setSkipIfSameApprover(this.isSkipIfSameApprover()); + 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, + skipIfSameApprover, + enable, + postponedMax, + schema, + 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(String sourceCode) { + return relations.stream() + .filter(relation -> relation.getSource().getCode().equals(sourceCode)) + .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..62b73d17 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/Opinion.java @@ -0,0 +1,127 @@ +package com.codingapi.springboot.flow.domain; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.util.ArrayList; +import java.util.List; + +/** + * 审批意见 + */ +@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; + // 审批结果 抄送 + public static final int RESULT_CIRCULATE = 4; + // 审批结果 等待 + public static final int RESULT_WAITING = 5; + // 审批结果 停止 + public static final int RESULT_STOP = 6; + + + /** + * 审批意见 + */ + private String advice; + /** + * 审批结果 + */ + private int result; + /** + * 意见类型 + */ + 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); + } + + 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); + } + + 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); + } + + 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; + } + + 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/ApprovalType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/ApprovalType.java new file mode 100644 index 00000000..ee58a275 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/ApprovalType.java @@ -0,0 +1,30 @@ +package com.codingapi.springboot.flow.em; + +/** + * 审批类型:会签与非会签 + */ +public enum ApprovalType { + + /** + * 会签 + */ + SIGN, + /** + * 非会签 + */ + UN_SIGN, + /** + * 传阅 + */ + CIRCULATE; + + + 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/FlowButtonType.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowButtonType.java new file mode 100644 index 00000000..550766f9 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowButtonType.java @@ -0,0 +1,31 @@ +package com.codingapi.springboot.flow.em; + +public enum FlowButtonType { + + // 保存 + SAVE, + // 发起 + START, + // 提交 + SUBMIT, + // 预提交 + TRY_SUBMIT, + // 指定人员提交 + SPECIFY_SUBMIT, + // 驳回 + REJECT, + // 转办 + TRANSFER, + // 撤销 + RECALL, + // 延期 + POSTPONED, + // 催办 + URGE, + // 自定义 + CUSTOM, + // 前端 + VIEW, + // 删除 + REMOVE, +} 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..4963f388 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowSourceDirection.java @@ -0,0 +1,34 @@ +package com.codingapi.springboot.flow.em; + +/** + * 流程来源的方式 + * 包括 同意、拒绝、转办 + */ +public enum FlowSourceDirection { + + /** + * 同意 + */ + PASS, + /** + * 拒绝 + */ + REJECT, + /** + * 转办 + */ + TRANSFER, + /** + * 传阅 + */ + CIRCULATE; + + 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..930eb03b --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/FlowType.java @@ -0,0 +1,42 @@ +package com.codingapi.springboot.flow.em; + +/** + * 流程的类型 + */ +public enum FlowType { + + /** + * 待办 + */ + TODO, + /** + * 已办 + */ + DONE, + /** + * 传阅 + */ + CIRCULATE, + /** + * 转办 + */ + TRANSFER, + /** + * 等待执行 + */ + WAITING, + /** + * 删除 + */ + DELETE; + + + 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..0386f857 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/em/NodeType.java @@ -0,0 +1,34 @@ +package com.codingapi.springboot.flow.em; + +/** + * 节点类型 + */ +public enum NodeType { + + /** + * 发起 + */ + START, + /** + * 审批 + */ + APPROVAL, + /** + * 传阅 + */ + CIRCULATE, + /** + * 结束 + */ + 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..4f21d62e --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/event/FlowApprovalEvent.java @@ -0,0 +1,135 @@ +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; + // 抄送 + public static final int STATE_CIRCULATE = 9; + // 保存 + 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; + // 停止 + public static final int STATE_STOP = 14; + + + 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(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() { + return state == STATE_URGE; + } + + public boolean isTodo() { + return state == STATE_TODO; + } + + public boolean isStop() { + return state == STATE_STOP; + } + + public boolean isSave() { + return state == STATE_SAVE; + } + + 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; + } + + 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/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..e383d076 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/matcher/OperatorMatcher.java @@ -0,0 +1,129 @@ +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.ArrayList; +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 specifyOperatorMatcher(List userIds) { + String userIdsStr = userIds.stream().map(String::valueOf).collect(Collectors.joining(",")); + return new OperatorMatcher("def run(content) {return [" + userIdsStr + "];}", STATE_SPECIFY); + } + + /** + * 创建者操作者匹配器 + * + * @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); + if (values == null) { + return new ArrayList<>(); + } + 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..5dc44e71 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java @@ -0,0 +1,130 @@ +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.FlowMerge; +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; + + /** + * 是否可以办理 + */ + private final boolean canHandle; + + /** + * 合并记录 + */ + private final List mergeRecords; + + + public FlowDetail(FlowRecord flowRecord, + List mergeRecords, + BindDataSnapshot snapshot, + FlowWork flowWork, + List historyRecords, + List operators, + boolean canHandle) { + this.operators = operators; + this.flowRecord = flowRecord; + this.mergeRecords = mergeRecords; + 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()); + 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.mergeRecords = null; + this.historyRecords = null; + this.bindData = null; + this.opinions = null; + this.flowCreator = null; + this.canHandle = canHandle; + } + + @Getter + 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(); + 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..1a825418 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowResult.java @@ -0,0 +1,47 @@ +package com.codingapi.springboot.flow.pojo; + +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 { + + 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); + } + + + /** + * 匹配操作者的记录 + * @param operator 操作者 + * @return 记录 + */ + 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); + } + + public boolean isStart() { + return records.stream().allMatch(FlowRecord::isStartNode); + } +} 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..8f4e94db --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowStepResult.java @@ -0,0 +1,51 @@ +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; +import java.util.List; +import java.util.stream.Collectors; + +@Getter +public class FlowStepResult { + + private final List flowNodes; + + public FlowStepResult() { + this.flowNodes = new ArrayList<>(); + } + + 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()+",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,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/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 new file mode 100644 index 00000000..1c365cfc --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/query/FlowRecordQuery.java @@ -0,0 +1,130 @@ +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 { + + + /** + * 根据ID获取流程记录 + * @param id 流程记录ID + * @return 流程记录 + */ + FlowRecord getFlowRecordById(long id); + + + /** + * 查询所有流程记录 + * @param pageRequest 分页参数 + * @return 流程记录 + */ + 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); + + /** + * 查看个人的待办数据 + * + * @param operatorId 操作人 + * @return 流程记录 + */ + Page findTodoByOperatorId(long operatorId, PageRequest pageRequest); + + + /** + * 查看个人的待办数据(指定流程) + * + * @param operatorId 操作人 + * @param workCode 流程编码 + * @return 流程记录 + */ + Page findTodoByOperatorId(long operatorId,String workCode, PageRequest pageRequest); + + + /** + * 查看个人的已办数据 + * @param operatorId 操作人 + * @return 流程记录 + */ + Page findDoneByOperatorId(long operatorId, PageRequest pageRequest); + + + /** + * 查看个人的已办数据 (指定流程) + * @param operatorId 操作人 + * @param workCode 流程编码 + * @return 流程记录 + */ + Page findDoneByOperatorId(long operatorId,String workCode, PageRequest pageRequest); + + /** + * 查看个人的发起数据 (含待办与已办) + * @param operatorId 操作人 + * @return 流程记录 + */ + Page findInitiatedByOperatorId(long operatorId, PageRequest pageRequest); + + + /** + * 查看个人的发起数据 (含待办与已办、指定流程) + * @param operatorId 操作人 + * @param workCode 流程编码 + * @return 流程记录 + */ + Page findInitiatedByOperatorId(long operatorId,String workCode, PageRequest pageRequest); + + /** + * 查看个人的超时的待办流程 + * @param operatorId 操作人 + * @return 流程记录 + */ + Page findTimeoutTodoByOperatorId(long operatorId, PageRequest pageRequest); + + /** + * 查看个人的超时的待办流程 (指定流程) + * @param operatorId 操作人 + * @param workCode 流程编码 + * @return 流程记录 + */ + Page findTimeoutTodoByOperatorId(long operatorId,String workCode, PageRequest pageRequest); + + /** + * 查看个人的延期的待办流程 + * @param operatorId 操作人 + * @return 流程记录 + */ + 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/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/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/FlowProcess.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowProcess.java new file mode 100644 index 00000000..46fcc892 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowProcess.java @@ -0,0 +1,56 @@ +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; + + + /** + * 是否作废 + */ + 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 new file mode 100644 index 00000000..2da107d2 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -0,0 +1,496 @@ +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; + + /** + * 流程编码 + */ + private String workCode; + + /** + * 流程id + */ + private String processId; + + /** + * 节点 + */ + private String nodeCode; + + + /** + * 是否可合并 + */ + private boolean mergeable; + + /** + * 流程标题 + */ + 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 circulate() { + this.flowSourceDirection = FlowSourceDirection.CIRCULATE; + this.flowType = FlowType.CIRCULATE; + this.updateTime = System.currentTimeMillis(); + this.opinion = Opinion.circulate(); + } + + + /** + * 停止流程 + */ + public void stop(){ + this.flowSourceDirection = FlowSourceDirection.PASS; + this.flowType = FlowType.DONE; + this.updateTime = System.currentTimeMillis(); + this.opinion = Opinion.stop(); + } + + /** + * 转交流程 + */ + 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 isWaiting() { + return this.flowType == FlowType.WAITING; + } + + /** + * 是否是待办 + */ + public boolean isTodo() { + return this.flowType == FlowType.TODO && this.flowStatus == FlowStatus.RUNNING; + } + + /** + * 是否是转交 + * + * @return 是否是转交 + */ + public boolean isTransfer() { + return this.flowType == FlowType.TRANSFER; + } + + + /** + * 拒绝状态 + */ + public boolean isReject() { + return this.opinion != null && this.opinion.isReject() && isDone(); + } + + /** + * 审批通过 + */ + 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 isCreateOperator(IFlowOperator operator) { + return this.createOperator.getUserId() == operator.getUserId(); + } + + /** + * 是否是当前操作者 + * + * @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 void delete() { + this.flowType = FlowType.DELETE; + 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.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); + 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 isDelete() { + return this.flowType == FlowType.DELETE; + } + + + /** + * 是否超时 + */ + 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; + } + + 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/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..a0d23ef9 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowProcessRepository.java @@ -0,0 +1,19 @@ +package com.codingapi.springboot.flow.repository; + +import com.codingapi.springboot.flow.domain.FlowWork; +import com.codingapi.springboot.flow.record.FlowProcess; + +/** + * 流程仓库,每一个流程都会在创建时被创建一条process数据,用于标识流程 + */ +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/repository/FlowRecordRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java new file mode 100644 index 00000000..8987ec6c --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java @@ -0,0 +1,89 @@ +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 workCode 流程编码 + * @param nodeCode 节点编码 + * @param currentOperatorId 当前操作者ID + * @return List of FlowRecord + */ + List findMergeFlowRecordById(String workCode,String nodeCode,long currentOperatorId); + + + /** + * 查询所有未完成的流程记录 + * + * @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); + + /** + * 根据流程id删除流程记录 + * @param processId 流程id + */ + void deleteByProcessId(String processId); + +} 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/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/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..b517104c --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java @@ -0,0 +1,105 @@ +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; +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; +import java.util.List; + +/** + * 流程节点序列化 + */ +@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 boolean mergeable; + + /** + * 创建时间 + */ + private long createTime; + /** + * 更新时间 + */ + private long updateTime; + + /** + * 超时时间(毫秒) + */ + private long timeout; + + /** + * 异常触发器,当流程发生异常时异常通常是指找不到审批人,将会触发异常触发器,异常触发器可以是一个节点 + */ + 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, mergeable, createTime, updateTime, timeout, errTrigger == null ? null : new ErrTrigger(errTrigger), buttons); + } +} 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..d25d039a --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowWorkSerializable.java @@ -0,0 +1,159 @@ +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; +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; + + /** + * 是否跳过相同审批人,默认为false + */ + @Setter + private boolean skipIfSameApprover; + + /** + * 是否启用 + */ + @Setter + private boolean enable; + + /** + * 最大延期次数 + */ + @Setter + private int postponedMax; + + /** + * 流程的schema + */ + private String schema; + + /** + * 流程的节点(发起节点) + */ + 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); + kryo.register(FlowButton.class); + kryo.register(FlowButtonType.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); + kryo.register(FlowButton.class); + kryo.register(FlowButtonType.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, + skipIfSameApprover, + postponedMax, + flowNodes, + relations.stream().map((item) -> item.toFlowRelation(flowNodes)).collect(Collectors.toList()), + 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 new file mode 100644 index 00000000..5ed0216c --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowDirectionService.java @@ -0,0 +1,96 @@ +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; + +/** + * 流程方向服务 + */ +public 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() || opinion.isWaiting()) { + flowSourceDirection = FlowSourceDirection.PASS; + } + if (opinion.isReject()) { + flowSourceDirection = FlowSourceDirection.REJECT; + } + } + + + /** + * 重新加载审批方向 + * 根据会签结果判断是否需要重新设置审批方向 + */ + public FlowSourceDirection reloadFlowSourceDirection() { + if (flowNode.isSign()) { + boolean allPass = historyRecords.stream().filter(item -> !item.isTransfer()) + .allMatch(item-> item.isPass() || item.getOpinion().isWaiting()); + 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() { + // 会签下所有人尚未提交时,不执行下一节点 + return historyRecords.stream().filter(item -> !item.isTransfer()).allMatch(FlowRecord::isDone); + } + + /** + * 判断当前流程是否为通过流程 + */ + public boolean isPassRecord() { + return flowSourceDirection == FlowSourceDirection.PASS; + } + + +} 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 new file mode 100644 index 00000000..facb0e47 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java @@ -0,0 +1,386 @@ +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.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.trigger.OutTrigger; +import com.codingapi.springboot.flow.user.IFlowOperator; +import com.codingapi.springboot.framework.event.EventPusher; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 流程节点服务 + */ +public class FlowNodeService { + + @Getter + private FlowNode nextNode; + private IFlowOperator nextOperator; + private IFlowOperator backOperator; + + private final FlowOperatorRepository flowOperatorRepository; + private final FlowRecordRepository flowRecordRepository; + + private final String processId; + private final long preId; + + private final FlowWork flowWork; + private final FlowRecord flowRecord; + private final Opinion opinion; + private final IFlowOperator currentOperator; + private final BindDataSnapshot snapshot; + private final List historyRecords; + private final IFlowOperator createOperator; + + + public FlowNodeService(FlowOperatorRepository flowOperatorRepository, + FlowRecordRepository flowRecordRepository, + BindDataSnapshot snapshot, + Opinion opinion, + IFlowOperator createOperator, + IFlowOperator currentOperator, + List historyRecords, + FlowWork flowWork, + FlowRecord flowRecord, + String processId, + long preId) { + + 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; + } + + + /** + * 设置下一个节点 + */ + 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(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() + .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() && record.getId()== currentRecord.getPreId()) { + // 是连续的回退节点时,则根据流程记录的状态来判断 + if(record.isReject()){ + 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(); + 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++; + } + } + + + + /** + * 获取下一个节点 + * + * @return 下一个节点 + */ + private FlowNode matcherNextNode(FlowNode flowNode, boolean back) { + 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())) + .collect(Collectors.toList()); + if (relations.isEmpty()) { + throw new IllegalArgumentException("relation not found"); + } + 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); + if (node != null) { + flowNodes.add(node); + } + } + if (flowNodes.isEmpty()) { + throw new IllegalArgumentException("next node not found"); + } + 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 = 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()); + } + 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, opinion.isWaiting()); + recordList.add(record); + } + } + return recordList; + } + + /** + * 异常匹配 + * + * @param currentNode 当前节点 + * @param currentOperator 当前操作者 + * @return 流程记录 + */ + private List errMatcher(FlowNode currentNode, IFlowOperator currentOperator) { + if (currentNode.hasErrTrigger()) { + 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."); + } + + // 匹配操作者 + 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(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); + } + 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(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, opinion.isWaiting()); + recordList.add(record); + } + } + return recordList; + } + throw new IllegalArgumentException("errMatcher not match."); + } + throw new IllegalArgumentException("operator not match."); + } + + + /** + * 下一节点的类型 + */ + public boolean nextNodeIsCirculate() { + return nextNode.isCirculate(); + } + + + /** + * 下一节点是否结束节点 + */ + public boolean nextNodeIsOver() { + return nextNode.isOverNode(); + } +} 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 new file mode 100644 index 00000000..01ecf875 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowRecordVerifyService.java @@ -0,0 +1,217 @@ +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.repository.FlowWorkRepository; +import com.codingapi.springboot.flow.user.IFlowOperator; +import lombok.Getter; + +import java.util.List; + +/** + * 流程记录服务(流程内部服务) + */ +public class FlowRecordVerifyService { + + // constructor params + @Getter + private final IFlowOperator currentOperator; + + // register repository + final FlowRecordRepository flowRecordRepository; + final FlowProcessRepository flowProcessRepository; + final FlowWorkRepository flowWorkRepository; + + // load Object + @Getter + private FlowWork flowWork; + @Getter + private FlowNode flowNode; + @Getter + 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; + + 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, + FlowRecord flowRecord, + FlowWork flowWork, + IFlowOperator currentOperator) { + this.flowWorkRepository = flowWorkRepository; + this.flowRecordRepository = flowRecordRepository; + this.flowProcessRepository = flowProcessRepository; + + this.currentOperator = currentOperator; + this.flowRecord = flowRecord; + this.flowWork = flowWork; + } + + + /** + * 校验流程记录是否已提交状态 + */ + public void verifyFlowRecordSubmitState() { + flowRecord.submitStateVerify(); + } + + /** + * 校验流程是否当前操作者可操作的 + */ + public void verifyFlowRecordCurrentOperator() { + if (!currentOperator.isFlowManager()) { + flowRecord.matcherOperator(currentOperator); + } + } + + /** + * 当前人是否为发起人 + * @return 是否为发起人 + */ + public boolean isCreateOperator() { + return flowRecord.isCreateOperator(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()) { + if (!flowRecord.isStartRecord()) { + 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 loadFlowWork() { + 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; + } + } + + + /** + * 获取流程节点对象 + */ + 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..a4c7862f --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowService.java @@ -0,0 +1,339 @@ +package com.codingapi.springboot.flow.service; + +import com.codingapi.springboot.flow.bind.IBindData; +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; +import com.codingapi.springboot.flow.service.impl.*; +import com.codingapi.springboot.flow.user.IFlowOperator; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + + +/** + * 流程服务 + */ +@Transactional +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; + private final FlowUrgeService flowUrgeService; + private final FlowVoidedService flowVoidedService; + private final FlowBackService flowBackService; + + private final FlowServiceRepositoryHolder flowServiceRepositoryHolder; + + + public FlowService(FlowWorkRepository flowWorkRepository, + FlowRecordRepository flowRecordRepository, + FlowBindDataRepository flowBindDataRepository, + 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.flowCustomEventService = new FlowCustomEventService(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); + this.flowUrgeService = new FlowUrgeService(flowWorkRepository, flowRecordRepository, flowProcessRepository); + this.flowVoidedService = new FlowVoidedService(flowWorkRepository, flowRecordRepository, flowProcessRepository, flowBindDataRepository); + this.flowBackService = new FlowBackService(flowWorkRepository, flowRecordRepository, flowProcessRepository, flowBindDataRepository); + } + + /** + * 流程详情 + * + * @param recordId 流程记录id + * @param workCode 流程编码 + * @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); + } + return null; + } + + /** + * 流程详情 + * + * @param recordId 流程记录id + * @return 流程详情 + */ + public FlowDetail detail(long recordId, IFlowOperator currentOperator) { + return this.detail(recordId, null, currentOperator); + } + + + /** + * 流程详情 + * + * @param workCode 流程编号 + * @return 流程详情 + */ + public FlowDetail detail(String workCode, IFlowOperator currentOperator) { + return this.detail(0, workCode, currentOperator); + } + + + /** + * 流程详情 + * + * @param recordId 流程记录id + * @return 流程详情 + */ + public FlowDetail detail(long recordId) { + return this.detail(recordId, null, null); + } + + /** + * 延期待办 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param time 延期时间 + */ + public void postponed(long recordId, IFlowOperator currentOperator, long time) { + flowPostponedService.postponed(recordId, currentOperator, time); + } + + /** + * 催办流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public void urge(long recordId, IFlowOperator currentOperator) { + flowUrgeService.urge(recordId, currentOperator); + } + + + /** + * 干预流程 + * + * @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) { + flowTransferService.transfer(recordId, currentOperator, targetOperator, bindData, advice); + } + + + /** + * 保存流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param advice 审批意见 + */ + public void save(long recordId, IFlowOperator currentOperator, IBindData bindData, String advice) { + flowSaveService.save(recordId, currentOperator, bindData, advice); + } + + + /** + * 发起流程 (不自动提交到下一节点) + * + * @param workCode 流程编码 + * @param operator 操作者 + * @param bindData 绑定数据 + * @param advice 审批意见 + */ + public FlowResult startFlow(String workCode, IFlowOperator operator, IBindData bindData, String advice) { + FlowStartService flowStartService = new FlowStartService(workCode, operator, bindData, advice, flowServiceRepositoryHolder); + return flowStartService.startFlow(); + } + + + /** + * 尝试提交流程 (流程过程中) + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public FlowSubmitResult trySubmitFlow(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + FlowTrySubmitService flowTrySubmitService = new FlowTrySubmitService(currentOperator, bindData, opinion, flowServiceRepositoryHolder); + return flowTrySubmitService.trySubmitFlow(recordId); + } + + + /** + * 获取流程执行节点 + * + * @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(); + } + + /** + * 获取流程执行节点 + * + * @param workCode + * @param currentOperator + * @return + */ + public FlowStepResult getFlowStep(String workCode, IBindData bindData, IFlowOperator currentOperator) { + FlowStepService flowStepService = new FlowStepService(0, workCode, currentOperator, bindData, flowServiceRepositoryHolder); + return flowStepService.getFlowStep(); + } + + /** + * 尝试提交流程 (发起流程) + * + * @param workCode 流程编码 + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public FlowSubmitResult trySubmitFlow(String workCode, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + FlowTrySubmitService flowTrySubmitService = new FlowTrySubmitService(currentOperator, bindData, opinion, flowServiceRepositoryHolder); + return flowTrySubmitService.trySubmitFlow(workCode); + } + + + /** + * 提交流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param bindData 绑定数据 + * @param opinion 审批意见 + */ + public FlowResult submitFlow(long recordId, IFlowOperator currentOperator, IBindData bindData, Opinion opinion) { + FlowSubmitService flowSubmitService = new FlowSubmitService(recordId, currentOperator, bindData, opinion, flowServiceRepositoryHolder); + return flowSubmitService.submitFlow(); + } + + /** + * 唤醒流程 + * + * @param processId 流程实例id + * @param currentOperator 当前操作者 + */ + public void notifyFlow(String processId, IFlowOperator currentOperator) { + FlowNotifyService flowNotifyService = new FlowNotifyService(processId, currentOperator, flowServiceRepositoryHolder); + flowNotifyService.notifyFlow(); + } + + /** + * 自定义事件 + * + * @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); + } + + + /** + * 撤回流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + 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); + } + + + /** + * 删除流程 + * + * @param recordId 流程记录id + * @param 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); + } + + /** + * 停止流程 + * + * @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/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/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/FlowCustomEventService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowCustomEventService.java new file mode 100644 index 00000000..67fbbbd8 --- /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.repository.FlowWorkRepository; +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 FlowWorkRepository flowWorkRepository; + 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(flowWorkRepository,flowRecordRepository, flowProcessRepository, recordId, currentOperator); + + // 验证流程的提交状态 + 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..718784d8 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java @@ -0,0 +1,124 @@ +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.FlowMerge; +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(flowWorkRepository,flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + flowRecordVerifyService.setFlowRecordRead(); + flowRecordVerifyService.loadFlowWork(); + + 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 = + 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,mergeRecords, 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/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/FlowPostponedService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowPostponedService.java new file mode 100644 index 00000000..68cbbc0f --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowPostponedService.java @@ -0,0 +1,45 @@ +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.repository.FlowWorkRepository; +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 FlowWorkRepository flowWorkRepository; + 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(flowWorkRepository,flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + 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..aeab8165 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRecallService.java @@ -0,0 +1,103 @@ +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; +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; + +@Transactional +@AllArgsConstructor +public class FlowRecallService { + + private final FlowWorkRepository flowWorkRepository; + private final FlowRecordRepository flowRecordRepository; + private final FlowProcessRepository flowProcessRepository; + private final FlowBindDataRepository flowBindDataRepository; + + /** + * 撤回流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + * @param backStartNode 是否退回到发起节点(仅限于流程创建者有效) + */ + public void recall(long recordId, IFlowOperator currentOperator,boolean backStartNode) { + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService( + flowWorkRepository, + flowRecordRepository, + flowProcessRepository, + recordId, + currentOperator); + + flowRecordVerifyService.verifyFlowRecordCurrentOperator(); + flowRecordVerifyService.loadFlowWork(); + flowRecordVerifyService.loadFlowNode(); + flowRecordVerifyService.verifyFlowRecordNotFinish(); + flowRecordVerifyService.verifyFlowRecordNotTodo(); + + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + BindDataSnapshot bindDataSnapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + + if(backStartNode && flowRecordVerifyService.isCreateOperator()){ + List records = flowRecordRepository.findFlowRecordByProcessId(flowRecord.getProcessId()); + for(FlowRecord record:records){ + if(!record.isStartRecord()) { + record.delete(); + flowRecordRepository.update(record); + }else { + record.recall(); + flowRecord = record; + flowRecordRepository.update(record); + } + } + }else { + // 下一流程的流程记录 + 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); + + 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); + } + + + /** + * 撤回流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public void recall(long recordId, IFlowOperator currentOperator) { + this.recall(recordId, currentOperator, 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 new file mode 100644 index 00000000..92a6a776 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowRemoveService.java @@ -0,0 +1,72 @@ +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.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.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 FlowRemoveService { + + private final FlowWorkRepository flowWorkRepository; + private final FlowRecordRepository flowRecordRepository; + private final FlowProcessRepository flowProcessRepository; + private final FlowBindDataRepository flowBindDataRepository; + + /** + * 删除流程 + * + * @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(); + FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + FlowNode flowNode = flowRecordVerifyService.getFlowNode(); + FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); + + if(!flowNode.isStartNode()){ + throw new IllegalArgumentException("flow record not remove"); + } + BindDataSnapshot bindDataSnapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + IBindData bindData = bindDataSnapshot.toBindData(); + + 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/FlowSaveService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java new file mode 100644 index 00000000..f73c6550 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSaveService.java @@ -0,0 +1,65 @@ +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.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.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; + +@Transactional +@AllArgsConstructor +public class FlowSaveService { + + private final FlowWorkRepository flowWorkRepository; + 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(flowWorkRepository, + flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + 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); + + 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 new file mode 100644 index 00000000..c8b8c127 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStartService.java @@ -0,0 +1,236 @@ +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.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.Getter; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Transactional +public class FlowStartService { + + 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; + } + + private void loadFlowWork() { + // 检测流程是否存在 + FlowWorkRepository flowWorkRepository = flowServiceRepositoryHolder.getFlowWorkRepository(); + this.flowWork = flowWorkRepository.getFlowWorkByCode(workCode); + if (flowWork == null) { + throw new IllegalArgumentException("flow work not found"); + } + flowWork.verify(); + flowWork.enableValidate(); + } + + private synchronized void loadFlowBackup() { + FlowBackupRepository flowBackupRepository = flowServiceRepositoryHolder.getFlowBackupRepository(); + this.flowBackup = flowBackupRepository.getFlowBackupByWorkIdAndVersion(flowWork.getId(), flowWork.getUpdateTime()); + if (flowBackup == null) { + flowBackup = flowBackupRepository.backup(flowWork); + } + } + + private void saveFlowProcess() { + this.flowProcess = new FlowProcess(flowBackup.getId(), operator); + flowServiceRepositoryHolder.getFlowProcessRepository().save(flowProcess); + } + + private void saveBindDataSnapshot() { + snapshot = new BindDataSnapshot(bindData); + flowServiceRepositoryHolder.getFlowBindDataRepository().save(snapshot); + } + + 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<>(); + + FlowOperatorRepository flowOperatorRepository = flowServiceRepositoryHolder.getFlowOperatorRepository(); + FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + + flowNodeService = new FlowNodeService(flowOperatorRepository, + flowRecordRepository, + snapshot, + opinion, + operator, + operator, + historyRecords, + flowWork, + null, + processId, + 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(); + 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(); + } + + this.saveFlowRecords(records); + + // 推送事件 + for (FlowRecord record : records) { + this.pushEvent(FlowApprovalEvent.STATE_CREATE, record); + this.pushEvent(FlowApprovalEvent.STATE_FINISH, record); + } + return new FlowResult(flowWork, records); + } + + // 保存流程记录 + this.saveFlowRecords(records); + + // 推送事件消息 + 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); + } + + + 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/FlowStepService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java new file mode 100644 index 00000000..6be110aa --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowStepService.java @@ -0,0 +1,116 @@ +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 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; + private final FlowServiceRepositoryHolder flowServiceRepositoryHolder; + + private FlowNodeService flowNodeService; + private FlowNode flowNode; + private FlowRecord currentFlowRecord; + + public FlowStepService(long recordId,String workCode, IFlowOperator currentOperator, IBindData bindData, FlowServiceRepositoryHolder flowServiceRepositoryHolder) { + this.recordId = recordId; + this.currentOperator = currentOperator; + this.bindData = bindData; + this.flowServiceRepositoryHolder = flowServiceRepositoryHolder; + 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(); + + // 设置开始流程的上一个流程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_" + RandomGenerator.generateUUID(); + + FlowOperatorRepository flowOperatorRepository = flowServiceRepositoryHolder.getFlowOperatorRepository(); + FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + List historyRecords = new ArrayList<>(); + BindDataSnapshot snapshot = new BindDataSnapshot(bindData); + flowNodeService = new FlowNodeService(flowOperatorRepository, + flowRecordRepository, + snapshot, + Opinion.pass("同意"), + currentOperator, + currentOperator, + historyRecords, + flowWork, + null, + processId, + preId); + + flowNodeService.setNextNode(this.flowNode); + + if(currentFlowRecord==null) { + flowStepResult.addFlowNode(this.flowNode, false, this.flowNodeService.loadNextNodeOperators()); + } + + do { + flowNodeService.loadNextPassNode(this.flowNode); + this.flowNode = flowNodeService.getNextNode(); + + boolean isFinish = currentFlowRecord != null && currentFlowRecord.isFinish(); + + flowStepResult.addFlowNode(this.flowNode,isFinish, this.flowNodeService.loadNextNodeOperators()); + } while (!flowNode.isOverNode()); + + return flowStepResult; + } +} 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/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..9b2eecc3 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowSubmitService.java @@ -0,0 +1,385 @@ +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.pojo.FlowSubmitResult; +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.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 org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Transactional +public class FlowSubmitService { + + + private final IFlowOperator currentOperator; + private final IBindData bindData; + private final Opinion opinion; + private final FlowServiceRepositoryHolder flowServiceRepositoryHolder; + private final FlowRecordVerifyService flowRecordVerifyService; + + + 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); + } + + + 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(); + // 加载流程节点 + flowRecordVerifyService.loadFlowNode(); + // 验证没有子流程 + flowRecordVerifyService.verifyChildrenRecordsIsEmpty(); + + if (testSubmit) { + this.flowRecord = flowRecordVerifyService.getFlowRecord().copy(); + } else { + this.flowRecord = flowRecordVerifyService.getFlowRecord(); + } + this.flowNode = flowRecordVerifyService.getFlowNode(); + this.flowWork = flowRecordVerifyService.getFlowWork(); + } + + // 保存流程表单快照数据 + private void saveSnapshot(boolean testSubmit) { + FlowBindDataRepository flowBindDataRepository = flowServiceRepositoryHolder.getFlowBindDataRepository(); + if (flowNode.isEditable()) { + snapshot = new BindDataSnapshot(bindData); + if (!testSubmit) { + flowBindDataRepository.save(snapshot); + } + } else { + snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); + } + } + + // 加载流程审批方向 + private void loadFlowDirection() { + // 审批方向判断服务 + flowDirectionService = new FlowDirectionService(flowRecordVerifyService.getFlowNode(), flowRecordVerifyService.getFlowWork(), opinion); + + // 加载流程审批方向 + flowDirectionService.loadFlowSourceDirection(); + // 验证审批方向 + flowDirectionService.verifyFlowSourceDirection(); + + flowSourceDirection = flowDirectionService.getFlowSourceDirection(); + } + + + // 与当前流程同级的流程记录 + private List loadHistoryRecords(boolean testSubmit) { + FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + // 与当前流程同级的流程记录 + List historyRecords; + if (flowRecord.isStartRecord()) { + historyRecords = new ArrayList<>(); + } else { + 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); + } + } + + } else { + historyRecords = flowRecordRepository.findFlowRecordByPreId(flowRecord.getPreId()); + } + } + return historyRecords; + } + + + // 保存流程记录 + private void saveFlowRecord(FlowRecord flowRecord) { + FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + flowRecordRepository.update(flowRecord); + } + + + // 生成下一节点的流程记录 + private void loadNextNode(List historyRecords) { + // 获取流程的发起者 + IFlowOperator createOperator = flowRecord.getCreateOperator(); + + // 构建流程创建器 + flowNodeService = new FlowNodeService( + flowServiceRepositoryHolder.getFlowOperatorRepository(), + flowServiceRepositoryHolder.getFlowRecordRepository(), + snapshot, + opinion, + createOperator, + currentOperator, + historyRecords, + flowWork, + flowRecord, + flowRecord.getProcessId(), + flowRecord.getId() + ); + + // 审批通过并进入下一节点 + if (flowDirectionService.isPassRecord()) { + flowNodeService.loadNextPassNode(flowNode); + } else { + flowNodeService.loadDefaultBackNode(flowNode,flowRecord); + } + this.nextNode = flowNodeService.getNextNode(); + } + + + // 更新流程记录 + private void updateFinishFlowRecord() { + flowServiceRepositoryHolder.getFlowRecordRepository().finishFlowRecordByProcessId(flowRecord.getProcessId()); + } + + // 保存流程记录 + private void saveNextFlowRecords(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() && !flowResult.isOver() && !flowResult.isStart()) { + 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.submitFlow(); + } + } + 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); + } + } + + // 非会签下,当有人提交以后,将所有未提交的流程都自动提交,然后再执行下一节点 + if (flowNode.isUnSign()) { + for (FlowRecord record : historyRecords) { + if (record.isTodo() && record.getId() != flowRecord.getId()) { + record.autoPass(record.getCurrentOperator(), snapshot); + FlowRecordRepository flowRecordRepository = flowServiceRepositoryHolder.getFlowRecordRepository(); + flowRecordRepository.update(record); + } + } + } + + // 根据所有提交意见,重新加载审批方向 + flowSourceDirection = flowDirectionService.reloadFlowSourceDirection(); + + this.loadNextNode(historyRecords); + + // 生成下一节点的流程记录 + List nextRecords = flowNodeService.createRecord(); + + // 判断流程是否完成 + if (flowNodeService.nextNodeIsOver()) { + flowRecord.submitRecord(currentOperator, snapshot, opinion, flowSourceDirection); + flowRecord.finish(); + this.saveFlowRecord(flowRecord); + this.updateFinishFlowRecord(); + + this.pushEvent(flowRecord, FlowApprovalEvent.STATE_FINISH); + + if (!nextRecords.isEmpty()) { + return new FlowResult(flowWork, nextRecords.get(0)); + } + return new FlowResult(flowWork, flowRecord); + } + + // 保存流程记录 + this.saveNextFlowRecords(nextRecords); + + // 推送审批事件消息 + int eventState = flowSourceDirection == FlowSourceDirection.PASS ? FlowApprovalEvent.STATE_PASS : FlowApprovalEvent.STATE_REJECT; + this.pushEvent(flowRecord, eventState); + + // 推送待办事件消息 + for (FlowRecord record : nextRecords) { + if(record.isTodo()) { + this.pushEvent(record, FlowApprovalEvent.STATE_TODO); + } + } + + 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); + + while (nextNode.isCirculate()){ + flowNodeService.skipCirculate(); + this.nextNode = flowNodeService.getNextNode(); + } + + 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 new file mode 100644 index 00000000..fc6e8007 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTransferService.java @@ -0,0 +1,101 @@ +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.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.ArrayList; +import java.util.Collections; +import java.util.List; + +@Transactional +@AllArgsConstructor +public class FlowTransferService { + + private final FlowWorkRepository flowWorkRepository; + 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(flowWorkRepository, flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + + 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..a136f492 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowTrySubmitService.java @@ -0,0 +1,44 @@ +package com.codingapi.springboot.flow.service.impl; + +import com.codingapi.springboot.flow.bind.IBindData; +import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.pojo.FlowSubmitResult; +import com.codingapi.springboot.flow.record.FlowRecord; +import com.codingapi.springboot.flow.service.FlowServiceRepositoryHolder; +import com.codingapi.springboot.flow.user.IFlowOperator; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +public class FlowTrySubmitService { + + 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; + } + + + public FlowSubmitResult trySubmitFlow(long recordId) { + FlowSubmitService flowSubmitService = new FlowSubmitService(recordId, currentOperator, bindData, opinion, flowServiceRepositoryHolder); + return flowSubmitService.trySubmitFlow(); + } + + + public FlowSubmitResult trySubmitFlow(String workCode) { + FlowStartService flowStartService = new FlowStartService(workCode, currentOperator, bindData, opinion.getAdvice(), flowServiceRepositoryHolder); + FlowRecord flowRecord = flowStartService.tryStartFlow(); + + 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 new file mode 100644 index 00000000..ba2acda2 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowUrgeService.java @@ -0,0 +1,53 @@ +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.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.List; + +@Transactional +@AllArgsConstructor +public class FlowUrgeService { + + + private final FlowWorkRepository flowWorkRepository; + private final FlowRecordRepository flowRecordRepository; + private final FlowProcessRepository flowProcessRepository; + + /** + * 催办流程 + * + * @param recordId 流程记录id + * @param currentOperator 当前操作者 + */ + public void urge(long recordId, IFlowOperator currentOperator) { + FlowRecordVerifyService flowRecordVerifyService = new FlowRecordVerifyService( + flowWorkRepository, + flowRecordRepository, + flowProcessRepository, + recordId, currentOperator); + 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/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/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-id-generator/src/test/java/com/codingapi/springboot/generator/IdGeneratorApplication.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/FlowTestApplication.java similarity index 57% rename from springboot-starter-id-generator/src/test/java/com/codingapi/springboot/generator/IdGeneratorApplication.java rename to springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/FlowTestApplication.java index d7979615..8a5c85d0 100644 --- a/springboot-starter-id-generator/src/test/java/com/codingapi/springboot/generator/IdGeneratorApplication.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/FlowTestApplication.java @@ -1,12 +1,12 @@ -package com.codingapi.springboot.generator; +package com.codingapi.springboot.flow; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class IdGeneratorApplication { +public class FlowTestApplication { public static void main(String[] args) { - SpringApplication.run(IdGeneratorApplication.class, 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..c7b3a7ca --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/flow/Leave.java @@ -0,0 +1,28 @@ +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; + 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/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/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..e1d96880 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowProcessRepositoryImpl.java @@ -0,0 +1,50 @@ +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)) + .filter(flowProcess -> !flowProcess.isVoided()) + .findFirst().orElse(null); + if (process == null) { + return null; + } + FlowBackup flowBackup = flowBackupRepository.getFlowBackupById(process.getBackupId()); + 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 new file mode 100644 index 00000000..f5d290a6 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java @@ -0,0 +1,226 @@ +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) + .filter(record -> !record.isDelete()) + .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) + .filter(record -> !record.isDelete()) + .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() + ) + .filter(record -> !record.isDelete()) + .collect(Collectors.toList()); + } + + @Override + public List findFlowRecordByProcessId(String 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()); + } + + @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.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) + .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) + .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) + .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) + ) + .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) + .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) + ) + .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) + .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)) + .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) + .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) + ).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) + .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) + ).filter(record -> !record.isDelete()) + .collect(Collectors.toList()); + return new PageImpl<>(flowRecords); + } + + @Override + public void finishFlowRecordByProcessId(String processId) { + cache.stream() + .filter(record -> record.getProcessId().equals(processId)) + .filter(record -> !record.isDelete()) + .forEach(FlowRecord::finish); + } + + @Override + 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/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..1342286b --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/LeaveRepository.java @@ -0,0 +1,23 @@ +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; + +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()); + } + } + 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/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..e9c739a9 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/BuildTest.java @@ -0,0 +1,52 @@ +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("抄送节点", "circulate", "default", ApprovalType.CIRCULATE, OperatorMatcher.anyOperatorMatcher()) + .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) + + .relations() + .relation("部门领导审批", "start", "dept") + .relation("总经理审批", "dept", "manager") + .relation("抄送节点", "manager", "circulate") + .relation("结束节点", "circulate", "over") + .build(); + assertEquals("请假流程", flowWork.getTitle()); + assertEquals(5, flowWork.getNodes().size()); + assertEquals(4, 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/CirculateTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/CirculateTest.java new file mode 100644 index 00000000..1a1c72cc --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/CirculateTest.java @@ -0,0 +1,143 @@ +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.pojo.FlowStepResult; +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, "发起流程"); + + + FlowStepResult result = flowService.getFlowStep(workCode, leave, user); + result.print(); + + // 查看我的待办 + 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 new file mode 100644 index 00000000..93408534 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java @@ -0,0 +1,292 @@ +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,false) + .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); + // 保存流程 + 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(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 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,false) + .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); + // 保存流程 + 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(2, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(2, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + 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/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/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-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/FlowRejectTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRejectTest.java new file mode 100644 index 00000000..bd63f867 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowRejectTest.java @@ -0,0 +1,458 @@ +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()); + + } + + + + /** + * 驳回测试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/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/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-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..1557436f --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java @@ -0,0 +1,1266 @@ +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.pojo.FlowStepResult; +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.trigger.OutTrigger; +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.*; + +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.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); + + FlowStepResult result = flowService.getFlowStep(workCode, leave, user); + result.print(); + + // 创建流程 + 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(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 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()); + + } + + + /** + * 同意再拒绝 + */ + @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(0, userTodos.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(2, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(3, 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.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); + // 保存流程 + 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(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 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,false) + .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); + 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(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(3, 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(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 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.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()); + + + // 转交给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(4, records.size()); + + 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(5, 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 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()); + } + + + /** + * 部门拒绝再提交测试 + */ + @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.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(5, records.size()); + + + } + + + /** + * 撤销流程测试 + */ + @Test + void recallTest1() { + 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()); + + 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.reject("不同意")); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, userTodos.size()); + + userTodo = userTodos.get(0); + flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(dept.getUserId())); + + 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(5, records.size()); + + + } + + + + /** + * 删除流程测试 + */ + @Test + void removeTest() { + 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()); + + } + + + /** + * 撤销流程测试 + */ + @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(1, records.size()); + + + } + + /** + * 非会签审批意见测试 + */ + @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-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..7ea093dc --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest2.java @@ -0,0 +1,298 @@ +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.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 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); + + /** + * 转办测试 + */ + @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(0, bossTodos.size()); + + List records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(5, records.size()); + + // 查看所有流程是否都已经结束 + 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.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("老板审批1", "boss", "boss1") + .relation("结束节点", "boss1", "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.pass("我提交了")); + + // 查看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.waiting("我等待提交")); + + userTodos = flowRecordRepository.findTodoByOperatorId(lorne.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + // 通知流程 + flowService.notifyFlow(processId,boss); + + // 查看boss的待办 + bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent(); + assertEquals(1, bossTodos.size()); + + 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(3, records.size()); + + // 查看所有流程是否都已经结束 + 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-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-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()); + + } +} 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..485286c9 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/MultiRelationFlowTest.java @@ -0,0 +1,201 @@ +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.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", "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(2, records.size()); + + // 最终用户确认 + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(2, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(3, 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.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", "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(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/QueryTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/QueryTest.java new file mode 100644 index 00000000..b4da2889 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/QueryTest.java @@ -0,0 +1,527 @@ +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.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); + 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(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()); + + 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.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()); + + // 查看我的超时待办 + 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(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()); + + 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.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.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(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()); + + 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.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); + 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(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)); + + FlowDetail flowDetail = flowService.detail(records.get(0).getId(), user); + assertEquals(3, flowDetail.getHistoryRecords().size()); + assertEquals(3, flowDetail.getOpinions().size()); + + List snapshots = flowBindDataRepository.findAll(); + assertEquals(4, snapshots.size()); + + + List userDones = flowRecordRepository.findDoneByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(1, 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()); + + assertTrue(bossDones.stream().allMatch(FlowRecord::isRead)); + } + + + /** + * 查询用户发起的流程 + */ + @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.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); + 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(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()); + + + + 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..a319393a --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java @@ -0,0 +1,44 @@ +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.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +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,\"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) + .build(); + assertEquals("请假流程", flowWork.getTitle()); + assertEquals(4, flowWork.getNodes().size()); + assertEquals(3, 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(3, 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..7f1abf00 --- /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(null,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..6c47cf15 --- /dev/null +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/SignTest.java @@ -0,0 +1,625 @@ +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.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; + +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.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(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(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()); + + } + + + /** + * 多人非会签拒绝测试 + */ + @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()); + + } + + + /** + * 多人会签测试 + */ + @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.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); + 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(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(7, 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.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); + 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(11, records.size()); + + userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent(); + assertEquals(0, userTodos.size()); + + records = flowRecordRepository.findAll(pageRequest).getContent(); + assertEquals(11, records.size()); + // 查看所有流程是否都已经结束 + assertTrue(records.stream().allMatch(FlowRecord::isFinish)); + + List snapshots = flowBindDataRepository.findAll(); + 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()); + + // 提交总经理的审批 + 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-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-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-id-generator/pom.xml b/springboot-starter-id-generator/pom.xml deleted file mode 100644 index c4adbf85..00000000 --- a/springboot-starter-id-generator/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - springboot-parent - com.codingapi.springboot - 2.1.11 - - 4.0.0 - - springboot-starter-id-generator - - - 17 - - - - - - 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 59332bc0..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/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/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 deleted file mode 100644 index 5ad14115..00000000 --- a/springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.codingapi.springboot.security.filter; - -import com.codingapi.springboot.security.dto.request.LoginRequest; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -public interface SecurityLoginHandler { - - void preHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest handler) throws Exception; -} 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 71% rename from springboot-starter-security-jwt/pom.xml rename to springboot-starter-security/pom.xml index 6369c486..24220084 100644 --- a/springboot-starter-security-jwt/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,16 +6,16 @@ springboot-parent com.codingapi.springboot - 2.1.11 + 2.10.26 - 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 - 17 + 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 63% 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 ba56c691..b8b21a76 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 @@ -2,9 +2,14 @@ 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.*; -import com.codingapi.springboot.security.jwt.Jwt; -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; @@ -24,6 +29,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 +61,53 @@ public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } + @Bean + @ConditionalOnMissingBean + public AuthenticationTokenFilter authenticationTokenFilter() { + return (request, response) -> { + + }; + } @Bean @ConditionalOnMissingBean - public SecurityLoginHandler securityLoginHandler(){ - return (request, response, handler) -> { + public HttpSecurityCustomer httpSecurityCustomer(CodingApiSecurityProperties properties){ + return new DefaultHttpSecurityCustomer(properties); + } + + @Bean + @ConditionalOnMissingBean + public SecurityLoginHandler securityLoginHandler() { + return new SecurityLoginHandler() { + @Override + public void preHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest handler) throws Exception { + + } + + @Override + 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()); + loginResponse.setAuthorities(token.getAuthorities()); + return loginResponse; + } }; } @Bean @ConditionalOnMissingBean - public SecurityFilterChain filterChain(HttpSecurity security, Jwt jwt,SecurityLoginHandler loginHandler, - SecurityJwtProperties properties) throws Exception { - //disable basic auth - security.httpBasic().disable(); - - //before add addCorsMappings to enable cors. - security.cors(); - if(properties.isDisableCsrf() ){ - security.csrf().disable(); - } - security.apply(new HttpSecurityConfigurer(jwt,loginHandler,properties)); + 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() .authenticationEntryPoint(new MyUnAuthenticationEntryPoint()) @@ -82,8 +115,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(); } ) @@ -113,19 +146,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("*") @@ -142,14 +169,14 @@ public void addCorsMappings(CorsRegistry registry) { @Bean @ConfigurationProperties(prefix = "codingapi.security") - public SecurityJwtProperties securityJwtProperties() { - return new SecurityJwtProperties(); + public CodingApiSecurityProperties codingApiSecurityProperties() { + return new CodingApiSecurityProperties(); } @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/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java similarity index 63% 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 d46a3a0b..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 @@ -1,10 +1,11 @@ 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; -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; @@ -13,15 +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)); + 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 7e5f3e75..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().requestMatchers(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 71% 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 index 7d2385a8..03e8445d 100644 --- 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 @@ -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", "-")); } } 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/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-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 91% 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 index cdfc3a3f..d717d36e 100644 --- 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 @@ -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-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/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java new file mode 100644 index 00000000..020ea664 --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/AuthenticationTokenFilter.java @@ -0,0 +1,13 @@ +package com.codingapi.springboot.security.filter; + +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)throws IOException, ServletException; + +} 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 74% 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 index 191d1dfc..beb79203 100644 --- 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 @@ -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; @@ -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-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 63% 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 09562919..232fd938 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,13 +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 jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +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; @@ -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; @@ -27,22 +26,24 @@ 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) { + 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; } @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); @@ -51,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()); } @@ -65,6 +66,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse } SecurityContextHolder.getContext().setAuthentication(token.getAuthenticationToken()); + authenticationTokenFilter.doFilter(request, response); } } chain.doFilter(request, response); @@ -73,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-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 71% 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 f472ed99..c0ecc62b 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; @@ -18,14 +18,14 @@ 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; -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; @@ -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 @@ -58,7 +58,7 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ throw new AuthenticationServiceException("request stream read was null."); } try { - loginHandler.preHandle(request,response,login); + loginHandler.preHandle(request, response, login); } catch (Exception e) { throw new AuthenticationServiceException(e.getLocalizedMessage()); } @@ -69,19 +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 = 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()); - LoginResponse login = new LoginResponse(); - login.setUsername(user.getUsername()); - login.setToken(token.getToken()); - login.setAuthorities(token.getAuthorities()); + 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"); - String content = JSONObject.toJSONString(SingleResponse.of(login)); IOUtils.write(content, response.getOutputStream(), StandardCharsets.UTF_8); LoginRequestContext.getInstance().clean(); @@ -92,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-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 82% 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 index a27c9d76..b2cbe8d2 100644 --- 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 @@ -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/src/main/java/com/codingapi/springboot/security/filter/MyLogoutSuccessHandler.java similarity index 73% 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 index 16a86c68..5b6520a6 100644 --- 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 @@ -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; @@ -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-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 73% 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 index ecc91b95..885b6241 100644 --- 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 @@ -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; @@ -20,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); } } 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 new file mode 100644 index 00000000..db7bc687 --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/filter/SecurityLoginHandler.java @@ -0,0 +1,17 @@ +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 org.springframework.security.core.userdetails.UserDetails; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +public interface SecurityLoginHandler { + + void preHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest loginRequest) throws Exception; + + LoginResponse postHandle(HttpServletRequest request, HttpServletResponse response, LoginRequest loginRequest, UserDetails userDetails, Token token); +} 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 64% 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 c1b7a2b8..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,28 +2,29 @@ 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; 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 { +public class JwtTokenGateway { - private final Key key; - private final int jwtTime; - private final int jwtRestTime; + private final SecretKey key; + 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,17 +37,17 @@ 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(); + 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; } 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失效,请重新登录."); 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 72% 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..0db1dad0 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,58 +5,48 @@ @Setter @Getter -public class SecurityJwtProperties { +public class CodingApiSecurityProperties { /** - * JWT密钥 - * 需大于32位的字符串 + * 权限拦截URL */ - private String jwtSecretKey = "codingapi.security.jwt.secretkey"; - + private String authenticatedUrls = "/api/**"; - /** - * aes key - */ - private String aseKey = "QUNEWCQlXiYqJCNYQ1phc0FDRFgkJV4mKiQjWENaYXM="; /** - * aes iv + * 登录接口地址 */ - private String aseIv = "QUNYRkdIQEVEUyNYQ1phcw=="; - + private String loginProcessingUrl = "/user/login"; /** - * JWT 有效时间(毫秒) - * 15分钟有效期 1000*60*15=900000 + * 退出登录接口地址 */ - private int jwtTime = 900000; + private String logoutUrl = "/user/logout"; /** - * JWT 更换令牌时间(毫秒) - * 10分钟后更换令牌 1000*60*10=600000 + * 放开接口地址 */ - private int jwtRestTime = 600000; + private String ignoreUrls = "/open/**"; /** - * 权限拦截URL + * aes key */ - private String authenticatedUrls = "/api/**"; - + private String aseKey = "QUNEWCQlXiYqJCNYQ1phc0FDRFgkJV4mKiQjWENaYXM="; /** - * 登录接口地址 + * aes iv */ - private String loginProcessingUrl = "/user/login"; + private String aseIv = "QUNYRkdIQEVEUyNYQ1phcw=="; /** - * 退出登录接口地址 + * 禁用Basic Auth */ - private String logoutUrl = "/user/logout"; + private boolean disableBasicAuth = true; /** - * 放开接口地址 + * 禁用FrameOptions */ - private String ignoreUrls = "/open/**"; + private boolean disableFrameOptions = true; /** * 启用禁用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..0e7d69f0 --- /dev/null +++ b/springboot-starter-security/src/main/java/com/codingapi/springboot/security/redis/RedisTokenGateway.java @@ -0,0 +1,110 @@ +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.ArrayList; +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; + } + + /** + * 根据token获取用户信息 + * + * @param token token + * @return 用户信息 + */ + public Token getToken(String token) { + String json = redisTemplate.opsForValue().get(token); + if (json == null) { + return null; + } + 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.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.isEmpty()) { + for (String key : keys) { + 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 new file mode 100644 index 00000000..8973f26d --- /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.getToken(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 92% 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 index 3872eadc..cd78167b 100644 --- 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 @@ -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-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 30709242..67b7a608 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,14 +5,14 @@ com.codingapi.springboot springboot-parent - 2.1.11 + 2.10.26 springboot-starter springboot-starter springboot-starter project for Spring Boot - 17 + 8 @@ -21,6 +21,16 @@ spring-data-commons + + jakarta.persistence + jakarta.persistence-api + + + + com.fasterxml.jackson.core + jackson-databind + + org.springframework spring-tx @@ -38,7 +48,7 @@ org.bouncycastle - bcprov-jdk15on + bcprov-jdk18on @@ -47,8 +57,8 @@ - org.apache.httpcomponents.client5 - httpclient5 + org.apache.httpcomponents + httpclient 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/annotation/ColumnType.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/ColumnType.java new file mode 100644 index 00000000..40bb84f1 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/annotation/ColumnType.java @@ -0,0 +1,52 @@ +package com.codingapi.springboot.framework.annotation; + +/** + * 数据库字段类型 + */ +public enum ColumnType { + + /** + * 整数 + */ + Number, + + /** + * 浮点数 + */ + Float, + + /** + * 字符串 + */ + String, + + /** + * 日期 + */ + Date, + + /** + * 文件 + */ + File, + + /** + * 布尔 + */ + Boolean, + + /** + * 字节 + */ + Bytes, + + /** + * JSON + */ + JSON, + + /** + * 任意 + */ + Any +} 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/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/Filter.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java new file mode 100644 index 00000000..c7223a90 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Filter.java @@ -0,0 +1,132 @@ +package com.codingapi.springboot.framework.dto.request; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class Filter { + + public static final String FILTER_OR_KEY = "FILTER_OR_KEY"; + public static final String FILTER_AND_KEY = "FILTER_AND_KEY"; + + 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(String key, Filter... value) { + this(key, 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 and(Filter... value) { + return new Filter(FILTER_AND_KEY, value); + } + + public static Filter or(Filter... value) { + return new Filter(FILTER_OR_KEY, value); + } + + 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; + } + + 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; + } + + public boolean isIn() { + return relation == Relation.IN; + } + + public boolean isOrFilters() { + return FILTER_OR_KEY.equals(key); + } + + public boolean isAndFilters() { + return FILTER_AND_KEY.equals(key); + } + + 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/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 b7af6da8..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 @@ -1,136 +1,64 @@ 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; -import org.springframework.data.domain.Pageable; +import lombok.Setter; 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.beans.PropertyDescriptor; -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 { @Getter + @Setter private int current; + + @Setter private int pageSize; - private final Map filters = new HashMap<>(); + @Getter + private Sort sort; @Getter - private HttpServletRequest servletRequest; + private final RequestFilter requestFilter = new RequestFilter(); - 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 = PageRequest.of(current, pageSize, sort); - - try { - ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); - this.servletRequest = attributes.getRequest(); - this.syncParameter(); - } catch (Exception e) { - } + this.sort = sort; } - private void syncParameter() { - Enumeration enumeration = servletRequest.getParameterNames(); - while (enumeration.hasMoreElements()) { - String key = enumeration.nextElement(); - String value = servletRequest.getParameter(key); - if (StringUtils.hasText(value)) { - this.filters.put(key, value); - } - } - } - public PageRequest() { this(0, 20, Sort.unsorted()); } - public void setCurrent(int current) { - this.current = current > 0 ? current - 1 : 0; - } - - 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 Map getFilters() { - return filters; - } - public String getStringFilter(String key) { - return (String) filters.get(key); + return requestFilter.getStringFilter(key); } + public String getStringFilter(String key, String defaultValue) { - String result = (String) filters.get(key); - return result == null ? defaultValue : result; + return requestFilter.getStringFilter(key, defaultValue); } public int getIntFilter(String key) { - return Integer.parseInt((String) filters.get(key)); - } - - public int getIntFilter(String key, int defaultValue) { - String result = (String) filters.get(key); - return result == null ? defaultValue : Integer.parseInt(result); + return requestFilter.getIntFilter(key); } - @Override - public int getPageSize() { - return pageSize; + public int getIntFilter(String key, int defaultValue) { + return requestFilter.getIntFilter(key, defaultValue); } - public void setPageSize(int pageSize) { - this.pageSize = pageSize; - } - @Override - public Sort getSort() { - return pageRequest.getSort(); - } - - @Override - public org.springframework.data.domain.PageRequest next() { - return new PageRequest(current + 1, getPageSize(), getSort()); + public boolean hasFilter() { + return requestFilter.hasFilter(); } - @Override - public org.springframework.data.domain.PageRequest previous() { - return current == 0 ? this : new PageRequest(current - 1, getPageSize(), getSort()); - } @Override - public org.springframework.data.domain.PageRequest first() { - return new PageRequest(0, getPageSize(), getSort()); + public int getPageSize() { + return pageSize; } @Override @@ -148,72 +76,44 @@ public boolean hasPrevious() { return current > 0; } - @Override - public Pageable previousOrFirst() { - return pageRequest.previousOrFirst(); - } - - @Override - public boolean isPaged() { - return pageRequest.isPaged(); + public void addSort(Sort sort) { + Sort nowSort = this.sort; + if (nowSort == Sort.unsorted()) { + this.sort = sort; + } else { + this.sort.and(sort); + } } - @Override - public boolean isUnpaged() { - return pageRequest.isUnpaged(); + public void removeFilter(String key) { + requestFilter.removeFilter(key); } - @Override - public Sort getSortOr(Sort sort) { - return pageRequest.getSortOr(sort); + public PageRequest addFilter(String key, Relation relation, Object... value) { + requestFilter.addFilter(key, relation, value); + return this; } - @Override - public Optional toOptional() { - return pageRequest.toOptional(); + public PageRequest addFilter(String key, Object... value) { + requestFilter.addFilter(key, value); + return this; } - public void addSort(Sort sort) { - Sort nowSort = pageRequest.getSort(); - if (nowSort == Sort.unsorted()) { - this.pageRequest = new PageRequest(getCurrent(), getPageSize(), sort); - } else { - pageRequest.getSort().and(sort); - } + public PageRequest andFilter(Filter... filters) { + requestFilter.andFilters(filters); + return this; } - public PageRequest addFilter(String key, Object value) { - this.filters.put(key, value); + public PageRequest orFilters(Filter... filters) { + requestFilter.orFilters(filters); return this; } - public boolean hasFilter() { - return !this.filters.isEmpty(); + public static PageRequest of(int page, int size) { + return new PageRequest(page, size, Sort.unsorted()); } - public Example getExample(Class clazz) { - if (!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(); - Object value = filters.get(name); - if (value != null) { - try { - descriptor.getWriteMethod().invoke(entity, value); - } catch (Exception e) { - } - } - } - return (Example) Example.of(entity); - + public static PageRequest of(int page, int size, Sort sort) { + return new PageRequest(page, size, sort); } } - 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..3fd9fce5 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/Relation.java @@ -0,0 +1,19 @@ +package com.codingapi.springboot.framework.dto.request; + +public enum Relation { + + NOT_EQUAL, + EQUAL, + LIKE, + LEFT_LIKE, + RIGHT_LIKE, + BETWEEN, + IN, + NOT_IN, + IS_NULL, + IS_NOT_NULL, + 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..0773eac8 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/RequestFilter.java @@ -0,0 +1,96 @@ +package com.codingapi.springboot.framework.dto.request; + +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +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 andFilters(Filter... value) { + this.pushFilter(new Filter(Filter.FILTER_AND_KEY, value)); + return this; + } + + public RequestFilter orFilters(Filter... value) { + this.pushFilter(new Filter(Filter.FILTER_OR_KEY, value)); + return this; + } + + public List getFilters() { + return filterList; + } + + public void pushFilter(Filter filter) { + filterList.removeIf(item -> item.getKey().equals(filter.getKey())); + filterList.add(filter); + filterMap.put(filter.getKey(), filter); + } + + + 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); + } + + public void removeFilter(String key) { + this.filterMap.remove(key); + this.filterList.removeIf(item -> item.getKey().equals(key)); + } +} 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 new file mode 100644 index 00000000..f14539ae --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/dto/request/SearchRequest.java @@ -0,0 +1,266 @@ +package com.codingapi.springboot.framework.dto.request; + +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; +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; +import java.util.Enumeration; +import java.util.List; +import java.util.stream.Collectors; + +/** + * HttpServletRequest 请求参数解析成 PageRequest对象 + */ +public class SearchRequest { + + @Getter + private int current; + @Getter + 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"); + } + + 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 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); + } + + 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); + } + + + 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, 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); + 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 -> parseObject(v, keyClass)) + .toArray() + ); + } + + + + private Class getKeyType(String key) { + String[] keys = key.split("\\."); + Class keyClass = clazz; + + for (String k : keys) { + 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(fieldName)) { + return field.getType(); + } + } + currentClass = currentClass.getSuperclass(); // 向上查找父类 + } + return null; + } + + } + + @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); + 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); + 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); + } + } + } + } + } + + Enumeration enumeration = request.getParameterNames(); + + while (enumeration.hasMoreElements()){ + String key = enumeration.nextElement(); + if (!removeKeys.contains(key)) { + String value = request.getParameter(key); + if (StringUtils.hasLength(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; + } + + +} 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; + +} 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/event/ApplicationHandlerUtils.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/ApplicationHandlerUtils.java new file mode 100644 index 00000000..61c7a932 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/ApplicationHandlerUtils.java @@ -0,0 +1,96 @@ +package com.codingapi.springboot.framework.event; + +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 { + + private static ApplicationHandlerUtils instance; + private final List> handlers; + + + private ApplicationHandlerUtils() { + this.handlers = new ArrayList<>(); + } + + public static ApplicationHandlerUtils getInstance() { + if (instance == null) { + synchronized (ApplicationHandlerUtils.class) { + if (instance == null) { + instance = new ApplicationHandlerUtils(); + } + } + } + return instance; + } + + public void addHandlers(List handlers) { + if (handlers != null) { + handlers.forEach(this::addHandler); + } + } + + + public void addHandler(IHandler handler) { + if (handler != null) { + handlers.add(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 hasThrowException = false; + for (IHandler handler : matchHandlers) { + try { + handler.handler(event); + } catch (Exception e) { + if (e instanceof EventLoopException) { + throw e; + } + try { + handler.error(e); + errorStack.add(e); + } catch (Exception err) { + hasThrowException = true; + errorStack.add(err); + } + } + } + if (hasThrowException) { + 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..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,15 @@ 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) { - context.publishEvent(new DomainEvent(event, sync)); + 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)); } } @@ -34,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/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..562e2768 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/event/EventTraceContext.java @@ -0,0 +1,107 @@ +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(); + } + + /** + * 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) { + 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(); + } + + /** + * add event + * @param traceId traceId + * @param event event + */ + 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); + } + + /** + * 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(); + } + } +} 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..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 @@ -1,6 +1,8 @@ package com.codingapi.springboot.framework.event; +import java.io.Serializable; + /** * 默认同步事件 *

@@ -8,7 +10,6 @@ * 事件本身不应该同步主业务的事务,即事件对于主业务来说,可成功可失败,成功与失败都不应该强关联主体业务。 * 若需要让主体业务与分支做事务同步的时候,那不应该采用事件机制,而应该直接采用调用的方式实现业务绑定。 */ -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 51% 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 45db5dd7..46248d8c 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,4 @@ -package com.codingapi.springboot.framework.handler; - -import com.codingapi.springboot.framework.event.IEvent; +package com.codingapi.springboot.framework.event; /** * handler 订阅 @@ -9,6 +7,14 @@ */ public interface IHandler { + /** + * 事件订阅排序 + * 在同样的事件中,可以通过order来控制订阅的顺序 + */ + default int order() { + return 0; + } + /** * 订阅触发 * @@ -18,12 +24,15 @@ public interface IHandler { /** * 异常回掉,在多订阅的情况下,为了实现订阅的独立性,将异常的处理放在回掉函数中。 + * 当异常抛出以后,会阻止后续的事件执行 * * @param exception 异常信息 */ - default void error(Exception exception) { + default void error(Exception exception) throws Exception { + throw exception; } - ; + + } 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 60% 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..141d3c53 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; @@ -27,12 +26,24 @@ public SpringEventHandler(List handlers) { } @Override - public void onApplicationEvent(DomainEvent domainEvent) { + public synchronized 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..dec33086 --- /dev/null +++ b/springboot-starter/src/main/java/com/codingapi/springboot/framework/exception/EventException.java @@ -0,0 +1,37 @@ +package com.codingapi.springboot.framework.exception; + +import lombok.Getter; + +import java.util.List; + +@Getter +public class EventException extends RuntimeException { + + private final List error; + + public EventException(List error) { + super(EventException.convert(error)); + this.error = error; + for (Exception e : error) { + 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(); + } +} 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/handler/ApplicationHandlerUtils.java b/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/ApplicationHandlerUtils.java deleted file mode 100644 index 7817ae56..00000000 --- a/springboot-starter/src/main/java/com/codingapi/springboot/framework/handler/ApplicationHandlerUtils.java +++ /dev/null @@ -1,85 +0,0 @@ -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 ApplicationHandlerUtils() { - this.handlers = new ArrayList<>(); - } - - public static ApplicationHandlerUtils getInstance() { - if (instance == null) { - synchronized (ApplicationHandlerUtils.class) { - if (instance == null) { - instance = new ApplicationHandlerUtils(); - } - } - } - return instance; - } - - public void addHandlers(List handlers) { - if (handlers != null) { - handlers.forEach(this::addHandler); - } - } - - - public void addHandler(IHandler handler) { - if (handler != null) { - handlers.add(handler); - } - } - - - @Override - public void handler(IEvent event) { - for (IHandler handler : handlers) { - String targetClassName = null; - try { - Class eventClass = event.getClass(); - Class targetClass = getHandlerEventClass(handler); - 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; - } - 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]; - } - } - } - return null; - } - - -} 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 51c08a8b..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 @@ -1,17 +1,18 @@ 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; import org.springframework.util.MultiValueMap; import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; +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(); @@ -35,19 +36,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) { - for (Object o : jsonArray) { - if (o instanceof JSONObject jsonObject) { - fetch(jsonObject, builder); - } - } - } } } } @@ -56,17 +44,31 @@ 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); } + @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/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()); + } +} 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)); } } 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/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; + } +} 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/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/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/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/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/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(); + } + } +} 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) { 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") 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..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 @@ -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()); @@ -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()); 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 +} 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