├── .github └── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── feature_request.yml │ └── other_issues.yml ├── .gitignore ├── APIJSONORM ├── .gitignore ├── README.md ├── pom.xml └── src │ └── main │ ├── java │ └── apijson │ │ ├── JSON.java │ │ ├── JSONCreator.java │ │ ├── JSONList.java │ │ ├── JSONMap.java │ │ ├── JSONParser.java │ │ ├── JSONRequest.java │ │ ├── JSONResponse.java │ │ ├── Log.java │ │ ├── MethodAccess.java │ │ ├── NotNull.java │ │ ├── RequestMethod.java │ │ ├── SQL.java │ │ ├── StringUtil.java │ │ ├── orm │ │ ├── AbstractFunctionParser.java │ │ ├── AbstractObjectParser.java │ │ ├── AbstractParser.java │ │ ├── AbstractSQLConfig.java │ │ ├── AbstractSQLExecutor.java │ │ ├── AbstractVerifier.java │ │ ├── Entry.java │ │ ├── FunctionParser.java │ │ ├── JSONRequest.java │ │ ├── Join.java │ │ ├── Logic.java │ │ ├── ObjectParser.java │ │ ├── OnParseCallback.java │ │ ├── Operation.java │ │ ├── Pair.java │ │ ├── Parser.java │ │ ├── ParserCreator.java │ │ ├── SQLConfig.java │ │ ├── SQLCreator.java │ │ ├── SQLExecutor.java │ │ ├── Subquery.java │ │ ├── Verifier.java │ │ ├── VerifierCreator.java │ │ ├── Visitor.java │ │ ├── exception │ │ │ ├── CommonException.java │ │ │ ├── ConditionErrorException.java │ │ │ ├── ConflictException.java │ │ │ ├── NotExistException.java │ │ │ ├── NotLoggedInException.java │ │ │ ├── OutOfRangeException.java │ │ │ ├── UnsupportedDataTypeException.java │ │ │ └── package-info.java │ │ ├── model │ │ │ ├── Access.java │ │ │ ├── AllColumn.java │ │ │ ├── AllColumnComment.java │ │ │ ├── AllTable.java │ │ │ ├── AllTableComment.java │ │ │ ├── Column.java │ │ │ ├── Document.java │ │ │ ├── ExtendedProperty.java │ │ │ ├── Function.java │ │ │ ├── PgAttribute.java │ │ │ ├── PgClass.java │ │ │ ├── Request.java │ │ │ ├── Script.java │ │ │ ├── SysColumn.java │ │ │ ├── SysTable.java │ │ │ ├── Table.java │ │ │ ├── TestRecord.java │ │ │ └── package-info.java │ │ ├── package-info.java │ │ └── script │ │ │ ├── JSR223ScriptExecutor.java │ │ │ ├── JavaScriptExecutor.java │ │ │ └── ScriptExecutor.java │ │ └── package-info.java │ └── resources │ └── application.properties ├── APIJSON初期构思及实现.docx ├── APIJSON初期构思及实现.pages ├── CONTRIBUTING.md ├── CONTRIBUTING_COMMIT.md ├── Document-English.md ├── Document.md ├── LICENSE ├── Navigation.md ├── README-English.md ├── README-extend.md ├── README.md ├── Roadmap.md ├── assets ├── 1542255627809.png ├── 1542338464474.png ├── 1542345654422.png ├── 1542345887787.png ├── 1542350018926.png ├── 1542350219020.png ├── 1542357146401.png ├── 1542357265371.png ├── 1543975054594.png ├── 1543975563775.png ├── 1543975563776.png ├── 1543978123163.png ├── 1543983739325.png ├── 1543983787388.png ├── 1544515879364.png ├── 1544659314099.png ├── 1545468294295.png ├── 1545468341131.png ├── 1545468361962.png └── a ├── logo.png └── 详细的说明文档.md /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report/报告 bug 2 | description: "Create a report to help us improve, please read FAQ first./帮助我们更好地改进项目,但请先阅读常见问题与提问前必看,不要提已有的重复问题!" 3 | title: "[Bug] " 4 | labels: [kind/bug] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: "如果你已经知道问题所在、怎么解决,请直接 提交 Pull Request 为社区做贡献,非常感谢。\n开发者也是人,也需要工作、休息、恋爱、陪伴家人、走亲会友等,也有心情不好和身体病痛,\n往往没有额外的时间精力顾及一些小问题,请理解和支持,开源要大家参与贡献才会更美好~\n少数个人的热情终有被耗尽的一天,只有大家共同建设和繁荣社区,才能让开源可持续发展! " 9 | 10 | - type: input 11 | attributes: 12 | label: APIJSON Version/APIJSON 版本号 13 | placeholder: | 14 | e.g./例如 5.4.0 ,如果不是最新版请用最新版,复现问题再来,原则上不更新旧版,而是只维护一个最新版 15 | 16 | validations: 17 | required: true 18 | 19 | - type: input 20 | attributes: 21 | label: Database Type & Version/数据库类型及版本号 22 | placeholder: | 23 | e.g./例如 MySQL 5.7.34 24 | 25 | validations: 26 | required: true 27 | 28 | - type: textarea 29 | attributes: 30 | label: Environment/环境信息 31 | description: | 32 | e.g./例如: 33 | - **JDK/基础库**: 1.8.0_17 34 | - **OS/系统**: MacOS Monterey 12.6 (21G115) M1 35 | value: | 36 | - JDK/基础库: 37 | - OS/系统: 38 | render: markdown 39 | 40 | validations: 41 | required: true 42 | 43 | - type: input 44 | attributes: 45 | label: APIAuto Screenshots/APIAuto 请求与结果完整截屏 46 | description: "Upload by copy and paste image file or url./复制图片文件或 URL 再粘贴到输入框(用 APIAuto 能静态检查出很多问题,甚至还有修复建议,不用浪费你我的时间)\n https://github.com/TommyLemon/APIAuto " 47 | value: 48 | 49 | validations: 50 | required: true 51 | 52 | - type: textarea 53 | attributes: 54 | label: Current Behavior/问题描述 55 | description: "A concise description of what you're experiencing. Must contains screenshots./\n\n**提 bug 请发请求和响应的【完整截屏】,没图的自行解决!\n开发者有限的时间和精力主要放在【维护项目源码和文档】上!\n【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!!\n【态度 不文明/不友善】的可能会被拉黑,问题也可能不予解答!!!**\n\n请求参数 JSON 中表名、字段名、关键词及对应的值都是大小写敏感、逗号敏感、分号敏感、空格敏感、换行敏感,\n大部分情况都不允许空格和换行,表名以大写字母开头,不要想当然,请严格按照 设计规范 来调用 API \n https://github.com/Tencent/APIJSON/issues/181 " 56 | render: markdown 57 | 58 | validations: 59 | required: true 60 | 61 | - type: textarea 62 | attributes: 63 | label: Expected Behavior/期望结果 64 | description: A concise description of what you expected to happen./具体描述你期望返回什么样的结果或者达到什么样的效果? 65 | render: markdown 66 | 67 | validations: 68 | required: false 69 | 70 | 71 | - type: textarea 72 | attributes: 73 | label: Any additional comments?/其它补充说明? 74 | description: | 75 | e.g. some background/context of how you ran into this bug./例如:一些背景或上下文信息,包括复现步骤、相关日志等 76 | render: markdown 77 | 78 | validations: 79 | required: false 80 | 81 | - type: markdown 82 | attributes: 83 | value: "Please follow the rules to fulfil all required inputs. You can add screenshots by comment after submit this issue./\n请按要求填写所有必填项,未填完将提交不了!\n如果随意填写敷衍了事,将直接关闭 issue,问题不会得到解答!\n可以提交后再通过回复评论来补充上传截屏图片(复制粘贴文件)。\n如果是网页 bug 等与你无关的原因导致提交不了,可以改为填问卷:\n https://wj.qq.com/s2/10971431/2a09 " 84 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request/期望新增功能 2 | description: Request a new feature/期望新增什么样的功能或特性,或者做哪些方面的改进? 3 | title: "[Feature] " 4 | labels: [kind/feature] 5 | body: 6 | - type: textarea 7 | attributes: 8 | label: Description 9 | description: | 10 | Please describe what this feature does./具体描述下是什么样的功能或特性,以及你为什么想要它,用在什么场景,碰到了什么痛点,有什么解决思路,尝试过哪些,效果怎样? 11 | 12 | validations: 13 | required: true 14 | 15 | - type: markdown 16 | attributes: 17 | value: 推荐去建议收集箱提问,也方便 统一检索和管理、投票决定优先级、更新处理进度 等: https://github.com/Tencent/APIJSON/issues/37 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/other_issues.yml: -------------------------------------------------------------------------------- 1 | name: Other Issues/其它反馈 2 | description: For questions, suggestions, improvements and others./问题(非 bug)、建议(非新增功能) 或 其它 3 | title: "[xxx] " 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: Description 8 | description: | 9 | Please describe the issue./请具体描述,包括是什么、为什么、如何做 10 | 11 | validations: 12 | required: true 13 | 14 | - type: markdown 15 | attributes: 16 | value: "Bug 反馈请使用正确的模板,用错模板将直接关闭 issue,不予解答:\n https://github.com/Tencent/APIJSON/issues/new?assignees=&labels=kind%2Fbug&template=bug_report.yml&title=%5BBug%5D+ \n有建议请去建议收集箱提问,也方便 统一检索和管理、投票决定优先级、更新处理进度 等:\n https://github.com/Tencent/APIJSON/issues/37 " 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .gradle 3 | yarn.lock 4 | *.project 5 | 6 | HELP.md 7 | target/ 8 | !.mvn/wrapper/maven-wrapper.jar 9 | !**/src/main/** 10 | !**/src/test/** 11 | 12 | ### STS ### 13 | .apt_generated 14 | .classpath 15 | .factorypath 16 | .project 17 | .settings 18 | .springBeans 19 | .sts4-cache 20 | 21 | ### IntelliJ IDEA ### 22 | .idea 23 | *.iws 24 | *.iml 25 | *.ipr 26 | 27 | ### NetBeans ### 28 | /nbproject/private/ 29 | /nbbuild/ 30 | /dist/ 31 | /nbdist/ 32 | /.nb-gradle/ 33 | build/ 34 | 35 | ### VS Code ### 36 | .vscode/ 37 | APIJSONORM/bin 38 | *.DS_Store 39 | -------------------------------------------------------------------------------- /APIJSONORM/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /APIJSONORM/README.md: -------------------------------------------------------------------------------- 1 | # APIJSONORM [![](https://jitpack.io/v/Tencent/APIJSON.svg)](https://jitpack.io/#Tencent/APIJSON) [Ask DeepWiki.com](https://deepwiki.com/Tencent/APIJSON) 2 | 腾讯 [APIJSON](https://github.com/Tencent/APIJSON) ORM 库,可通过 Maven, Gradle 等远程依赖。
3 | Tencent [APIJSON](https://github.com/Tencent/APIJSON) ORM library for remote dependencies with Maven, Gradle, etc. 4 | 5 | ### Maven 6 | #### 1. 在 pom.xml 中添加 JitPack 仓库 7 | #### 1. Add the JitPack repository to pom.xml 8 | ```xml 9 | 10 | 11 | jitpack.io 12 | https://jitpack.io 13 | 14 | 15 | ``` 16 |
17 | 18 | #### 2. 在 pom.xml 中添加 APIJSON 依赖 19 | #### 2. Add the APIJSON dependency to pom.xml 20 | ```xml 21 | 22 | com.github.Tencent 23 | APIJSON 24 | LATEST 25 | 26 | ``` 27 | 28 |
29 |
30 | 31 | ### Gradle 32 | #### 1. 在项目根目录 build.gradle 中最后添加 JitPack 仓库 33 | #### 1. Add the JitPack repository in your root build.gradle at the end of repositories 34 | ```gradle 35 | allprojects { 36 | repositories { 37 | ... 38 | maven { url 'https://jitpack.io' } 39 | } 40 | } 41 | ``` 42 |
43 | 44 | #### 2. 在项目某个 module 目录(例如 `app`) build.gradle 中添加 apijson-orm 依赖 45 | #### 2. Add the APIJSON dependency in one of your modules(such as `app`) 46 | ```gradle 47 | dependencies { 48 | implementation 'com.github.Tencent:APIJSON:latest' 49 | } 50 | ``` 51 | 52 |
53 |
54 | 55 | ### FASTJSON 2 56 | #### Code 57 | https://github.com/Tencent/APIJSON/tree/fastjson2 58 | 59 | #### Maven 60 | https://mvnrepository.com/artifact/com.github.linushp/zikai-apijson/1.0 61 | 62 |
63 | 64 | ### Unit Test 65 | http://apijson.cn/unit 66 | -------------------------------------------------------------------------------- /APIJSONORM/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.github.Tencent 7 | APIJSON 8 | 8.0.0 9 | jar 10 | 11 | APIJSONORM 12 | APIJSON ORM Library 13 | 14 | 15 | UTF-8 16 | UTF-8 17 | 1.8 18 | UTF-8 19 | 1.8 20 | 1.8 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | org.apache.maven.plugins 30 | maven-compiler-plugin 31 | 3.12.1 32 | 33 | 1.8 34 | 1.8 35 | 36 | 37 | 38 | 39 | org.apache.maven.plugins 40 | maven-source-plugin 41 | 3.2.1 42 | 43 | 44 | package 45 | 46 | jar-no-fork 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/JSONCreator.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson; 7 | 8 | import java.util.Collection; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /**JSON相关创建器 13 | * @author Lemon 14 | */ 15 | public interface JSONCreator, L extends List> { 16 | 17 | @NotNull 18 | M createJSONObject(); 19 | 20 | @NotNull 21 | default M createJSONObject(String key, Object value) { 22 | M obj = createJSONObject(); 23 | obj.put(key, value); 24 | return obj; 25 | } 26 | 27 | @NotNull 28 | default M createJSONObject(Map map) { 29 | M obj = createJSONObject(); 30 | if (map != null && ! map.isEmpty()) { 31 | obj.putAll(map); 32 | } 33 | return obj; 34 | } 35 | 36 | @NotNull 37 | L createJSONArray(); 38 | 39 | @NotNull 40 | default L createJSONArray(Object obj){ 41 | L arr = createJSONArray(); 42 | arr.add(obj); 43 | return arr; 44 | } 45 | 46 | @NotNull 47 | default L createJSONArray(Collection list){ 48 | L arr = createJSONArray(); 49 | if (list != null && ! list.isEmpty()) { 50 | arr.addAll(list); 51 | } 52 | return arr; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/JSONList.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | package apijson; 6 | 7 | import java.util.*; 8 | 9 | /** 10 | * Custom JSONList implementation based on ArrayList to replace com.alibaba.fastjson.JSONList 11 | * Maintains same API as fastjson but uses standard Java List implementation 12 | * @author Lemon 13 | */ 14 | public interface JSONList, L extends List> extends List { 15 | public static final String TAG = "JSONList"; 16 | 17 | ///** 18 | // * Create an empty JSONList 19 | // */ 20 | //default JSONList() { 21 | // super(); 22 | //} 23 | // 24 | //private int initialCapacity = 10; 25 | ///** 26 | // * Create a JSONList with initial capacity 27 | // * @param initialCapacity the initial capacity 28 | // */ 29 | //default JSONList(int initialCapacity) { 30 | // super(initialCapacity); 31 | //} 32 | // 33 | ///** 34 | // * Create a JSONList from a Collection 35 | // * @param collection the collection to copy from 36 | // */ 37 | //default JSONList(Collection collection) { 38 | // super(collection); 39 | //} 40 | // 41 | ///** 42 | // * Create a JSONList from a JSON string 43 | // * @param json JSON string 44 | // */ 45 | //default JSONList(String json) { 46 | // this(); 47 | // List list = JSON.parseArray(json); 48 | // if (list != null) { 49 | // addAll(list); 50 | // } 51 | //} 52 | // 53 | /** 54 | * Get a JSONMap at the specified index 55 | * @param index the index 56 | * @return the JSONMap or null if not a JSONMap 57 | */ 58 | default M getJSONObject(int index) { 59 | if (index < 0 || index >= size()) { 60 | return null; 61 | } 62 | 63 | Object obj = get(index); 64 | if (obj instanceof Map) { 65 | return JSON.createJSONObject((Map) obj); 66 | } 67 | 68 | return null; 69 | } 70 | 71 | /** 72 | * Get a JSONList at the specified index 73 | * @param index the index 74 | * @return the JSONList or null if not a JSONList 75 | */ 76 | default L getJSONArray(int index) { 77 | if (index < 0 || index >= size()) { 78 | return null; 79 | } 80 | 81 | Object obj = get(index); 82 | if (obj instanceof List) { 83 | return JSON.createJSONArray((List) obj); 84 | } 85 | 86 | return null; 87 | } 88 | 89 | /** 90 | * Get a boolean value at the specified index 91 | * @param index the index 92 | * @return the boolean value or false if not found 93 | */ 94 | default boolean getBooleanValue(int index) { 95 | if (index < 0 || index >= size()) { 96 | return false; 97 | } 98 | 99 | Object obj = get(index); 100 | if (obj instanceof Boolean) { 101 | return (Boolean) obj; 102 | } else if (obj instanceof Number) { 103 | return ((Number) obj).intValue() != 0; 104 | } else if (obj instanceof String) { 105 | return Boolean.parseBoolean((String) obj); 106 | } 107 | 108 | return false; 109 | } 110 | 111 | /** 112 | * Get an integer value at the specified index 113 | * @param index the index 114 | * @return the integer value or 0 if not found 115 | */ 116 | default int getIntValue(int index) { 117 | if (index < 0 || index >= size()) { 118 | return 0; 119 | } 120 | 121 | Object obj = get(index); 122 | if (obj instanceof Number) { 123 | return ((Number) obj).intValue(); 124 | } else if (obj instanceof String) { 125 | try { 126 | return Integer.parseInt((String) obj); 127 | } catch (NumberFormatException e) { 128 | // Ignore 129 | } 130 | } 131 | return 0; 132 | } 133 | 134 | /** 135 | * Get a long value at the specified index 136 | * @param index the index 137 | * @return the long value or 0 if not found 138 | */ 139 | default long getLongValue(int index) { 140 | if (index < 0 || index >= size()) { 141 | return 0L; 142 | } 143 | 144 | Object obj = get(index); 145 | if (obj instanceof Number) { 146 | return ((Number) obj).longValue(); 147 | } else if (obj instanceof String) { 148 | try { 149 | return Long.parseLong((String) obj); 150 | } catch (NumberFormatException e) { 151 | // Ignore 152 | } 153 | } 154 | return 0L; 155 | } 156 | 157 | /** 158 | * Get a double value at the specified index 159 | * @param index the index 160 | * @return the double value or 0 if not found 161 | */ 162 | default double getDoubleValue(int index) { 163 | if (index < 0 || index >= size()) { 164 | return 0.0; 165 | } 166 | 167 | Object obj = get(index); 168 | if (obj instanceof Number) { 169 | return ((Number) obj).doubleValue(); 170 | } else if (obj instanceof String) { 171 | try { 172 | return Double.parseDouble((String) obj); 173 | } catch (NumberFormatException e) { 174 | // Ignore 175 | } 176 | } 177 | return 0.0; 178 | } 179 | 180 | /** 181 | * Get a string value at the specified index 182 | * @param index the index 183 | * @return the string value or null if not found 184 | */ 185 | default String getString(int index) { 186 | if (index < 0 || index >= size()) { 187 | return null; 188 | } 189 | 190 | Object obj = get(index); 191 | return obj != null ? obj.toString() : null; 192 | } 193 | 194 | 195 | default String toJSONString() { 196 | return JSON.toJSONString(this); 197 | } 198 | 199 | //@Override 200 | //default boolean containsAll(Collection c) { 201 | // if (c == null || c.isEmpty()) { 202 | // return true; 203 | // } 204 | // return super.containsAll(c); 205 | //} 206 | // 207 | //@Override 208 | //default boolean addAll(Collection c) { 209 | // if (c == null || c.isEmpty()) { 210 | // return true; 211 | // } 212 | // return super.addAll(c); 213 | //} 214 | // 215 | //@Override 216 | //default boolean addAll(int index, Collection c) { 217 | // if (c == null || c.isEmpty()) { 218 | // return true; 219 | // } 220 | // 221 | // int sz = size(); 222 | // if (index < 0 || index >= sz) { 223 | // index += sz; 224 | // } 225 | // 226 | // return super.addAll(index, c); 227 | //} 228 | // 229 | //@Override 230 | //default boolean removeAll(Collection c) { 231 | // if (c == null || c.isEmpty()) { 232 | // return true; 233 | // } 234 | // return super.removeAll(c); 235 | //} 236 | // 237 | //@Override 238 | //default boolean retainAll(Collection c) { 239 | // if (c == null || c.isEmpty()) { 240 | // return true; 241 | // } 242 | // return super.retainAll(c); 243 | //} 244 | // 245 | // 246 | //@Override 247 | //default Object get(int index) { 248 | // int sz = size(); 249 | // if (index < 0 || index >= sz) { 250 | // index += sz; 251 | // } 252 | // 253 | // return super.get(index); 254 | //} 255 | // 256 | //@Override 257 | //default Object set(int index, Object element) { 258 | // int sz = size(); 259 | // if (index < 0 || index >= sz) { 260 | // index += sz; 261 | // } 262 | // 263 | // return super.set(index, element); 264 | //} 265 | // 266 | //@Override 267 | //default void add(int index, Object element) { 268 | // int sz = size(); 269 | // if (index < 0 || index >= sz) { 270 | // index += sz; 271 | // } 272 | // 273 | // super.add(index, element); 274 | //} 275 | // 276 | //@Override 277 | //default Object remove(int index) { 278 | // int sz = size(); 279 | // if (index < 0 && index >= -sz) { 280 | // index += sz; 281 | // } 282 | // if (index < 0 || index >= sz) { 283 | // return null; 284 | // } 285 | // 286 | // return super.remove(index); 287 | //} 288 | // 289 | //@Override 290 | //default ListIterator listIterator(int index) { 291 | // int sz = size(); 292 | // if (index < 0 && index >= -sz) { 293 | // index += sz; 294 | // } 295 | // 296 | // return super.listIterator(index); 297 | //} 298 | // 299 | //@Override 300 | //default List subList(int fromIndex, int toIndex) { 301 | // int sz = size(); 302 | // if (fromIndex < 0 && fromIndex >= -sz) { 303 | // fromIndex += sz; 304 | // } 305 | // if (toIndex < 0 && toIndex >= -sz) { 306 | // toIndex += sz; 307 | // } 308 | // 309 | // return super.subList(fromIndex, toIndex); 310 | //} 311 | 312 | } -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/JSONParser.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /**JSON 相关解析器 12 | * @author Lemon 13 | */ 14 | public interface JSONParser, L extends List> extends JSONCreator { 15 | 16 | Object parse(Object json); 17 | 18 | M parseObject(Object json); 19 | 20 | T parseObject(Object json, Class clazz); 21 | 22 | L parseArray(Object json); 23 | 24 | List parseArray(Object json, Class clazz); 25 | 26 | default String format(Object obj) { 27 | return toJSONString(obj, true); 28 | } 29 | default String toJSONString(Object obj) { 30 | return toJSONString(obj, false); 31 | } 32 | String toJSONString(Object obj, boolean format); 33 | } 34 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/JSONRequest.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | import static apijson.StringUtil.PATTERN_ALPHA_BIG; 14 | 15 | /**wrapper for request 16 | * @author Lemon 17 | * @see #puts 18 | * @see #toArray 19 | * @use JSONRequest request = JSON.createJSONObject(...); 20 | *
request.puts(...);//not a must 21 | *
request.toArray(...);//not a must 22 | */ 23 | public interface JSONRequest, L extends List> extends JSONMap { 24 | 25 | //default JSONRequest() { 26 | // super(); 27 | //} 28 | ///** 29 | // * @param object must be annotated by {@link MethodAccess} 30 | // * @see {@link #JSONRequest(String, Object)} 31 | // */ 32 | //default JSONRequest(Object object) { 33 | // this(null, object); 34 | //} 35 | ///** 36 | // * @param name 37 | // * @param object 38 | // * @see {@link #puts(String, Object)} 39 | // */ 40 | //default JSONRequest(String name, Object object) { 41 | // this(); 42 | // puts(name, object); 43 | //} 44 | 45 | //public static JSONRequest valueOf(Object obj) { 46 | // JSONRequest req = new JSONRequest() {}; 47 | // Map m = JSON.parseObject(obj); 48 | // if (m != null && ! m.isEmpty()) { 49 | // req.map.putAll(m); 50 | // } 51 | // return req; 52 | //} 53 | 54 | public static final String KEY_TAG = "tag";//只在最外层,最外层用JSONRequest 55 | public static final String KEY_VERSION = "version";//只在最外层,最外层用JSONRequest 56 | public static final String KEY_FORMAT = "format";//只在最外层,最外层用JSONRequest 57 | 58 | /**set "tag":tag in outermost layer 59 | * for write operations 60 | * @param tag 61 | * @return 62 | */ 63 | default JSONRequest setTag(String tag) { 64 | return puts(KEY_TAG, tag); 65 | } 66 | 67 | /**set "version":version in outermost layer 68 | * for target version of request 69 | * @param version 70 | * @return 71 | */ 72 | default JSONRequest setVersion(Integer version) { 73 | return puts(KEY_VERSION, version); 74 | } 75 | 76 | /**set "format":format in outermost layer 77 | * for format APIJSON special keys to normal keys of response 78 | * @param format 79 | * @return 80 | */ 81 | default JSONRequest setFormat(Boolean format) { 82 | return puts(KEY_FORMAT, format); 83 | } 84 | 85 | 86 | //array object <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 87 | 88 | public static final int QUERY_TABLE = 0; 89 | public static final int QUERY_TOTAL = 1; 90 | public static final int QUERY_ALL = 2; 91 | 92 | public static final String QUERY_TABLE_STRING = "TABLE"; 93 | public static final String QUERY_TOTAL_STRING = "TOTAL"; 94 | public static final String QUERY_ALL_STRING = "ALL"; 95 | 96 | public static final String SUBQUERY_RANGE_ALL = "ALL"; 97 | public static final String SUBQUERY_RANGE_ANY = "ANY"; 98 | 99 | public static final String KEY_QUERY = "query"; 100 | public static final String KEY_COMPAT = "compat"; 101 | public static final String KEY_COUNT = "count"; 102 | public static final String KEY_PAGE = "page"; 103 | public static final String KEY_JOIN = "join"; 104 | public static final String KEY_SUBQUERY_RANGE = "range"; 105 | public static final String KEY_SUBQUERY_FROM = "from"; 106 | 107 | public static final List ARRAY_KEY_LIST = new ArrayList<>(Arrays.asList( 108 | KEY_QUERY, KEY_COMPAT ,KEY_COUNT, KEY_PAGE, KEY_JOIN, KEY_SUBQUERY_RANGE, KEY_SUBQUERY_FROM 109 | )); 110 | 111 | /**set what to query in Array layer 112 | * @param query what need to query, Table,total,ALL? 113 | * @return 114 | * @see {@link #QUERY_TABLE} 115 | * @see {@link #QUERY_TOTAL} 116 | * @see {@link #QUERY_ALL} 117 | */ 118 | default JSONRequest setQuery(int query) { 119 | return puts(KEY_QUERY, query); 120 | } 121 | 122 | /**set maximum count of Tables to query in Array layer 123 | * @param count <= 0 || >= max ? max : count 124 | * @return 125 | */ 126 | default JSONRequest setCount(int count) { 127 | return puts(KEY_COUNT, count); 128 | } 129 | 130 | /**set page of Tables to query in Array layer 131 | * @param page <= 0 ? 0 : page 132 | * @return 133 | */ 134 | default JSONRequest setPage(int page) { 135 | return puts(KEY_PAGE, page); 136 | } 137 | 138 | /**set joins of Main Table and it's Vice Tables in Array layer 139 | * @param joins "@/User/id@", "&/User/id@,>/Comment/momentId@" ... 140 | * @return 141 | */ 142 | default JSONRequest setJoin(String... joins) { 143 | return setJson(this, StringUtil.get(joins)); 144 | } 145 | 146 | public static > M setJson(M m, String... joins) { 147 | m.put(KEY_JOIN, StringUtil.get(joins)); 148 | return m; 149 | } 150 | 151 | /**set range for Subquery 152 | * @param range 153 | * @return 154 | * @see {@link #SUBQUERY_RANGE_ALL} 155 | * @see {@link #SUBQUERY_RANGE_ANY} 156 | */ 157 | default JSONRequest setSubqueryRange(String range) { 158 | return puts(KEY_SUBQUERY_RANGE, range); 159 | } 160 | 161 | /**set from for Subquery 162 | * @param from 163 | * @return 164 | */ 165 | default JSONRequest setSubqueryFrom(String from) { 166 | return puts(KEY_SUBQUERY_FROM, from); 167 | } 168 | 169 | //array object >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 170 | 171 | 172 | /**create a parent JSONMap named KEY_ARRAY 173 | * @param count 174 | * @param page 175 | * @return {@link #toArray(int, int)} 176 | */ 177 | default M toArray(int count, int page) { 178 | return toArray(count, page, null); 179 | } 180 | 181 | /**create a parent JSONMap named name+KEY_ARRAY. 182 | * @param count 183 | * @param page 184 | * @param name 185 | * @return {name+KEY_ARRAY : this}. if needs to be put, use {@link #putsAll(Map)} instead 186 | */ 187 | default M toArray(int count, int page, String name) { 188 | return JSON.createJSONObject(StringUtil.get(name) + KEY_ARRAY, this.setCount(count).setPage(page)); 189 | } 190 | 191 | 192 | @Override 193 | default JSONRequest putsAll(Map map) { 194 | putAll(map); 195 | return this; 196 | } 197 | 198 | @Override 199 | default JSONRequest puts(Object value) { 200 | put(value); 201 | return this; 202 | } 203 | 204 | @Override 205 | default JSONRequest puts(String key, Object value) { 206 | put(key, value); 207 | return this; 208 | } 209 | 210 | 211 | /**ABCdEfg => upper ? A-B-CD-EFG : a-b-cd-efg 212 | * @param key 213 | * @return 214 | */ 215 | public static String recoverHyphen(@NotNull String key, Boolean upper) { 216 | return recoverDivider(key, "-", upper); 217 | } 218 | 219 | /**ABCdEfg => upper ? A_B_CD_EFG : a_b_cd_efg 220 | * @param key 221 | * @return 222 | */ 223 | public static String recoverUnderline(@NotNull String key, Boolean upper) { 224 | return recoverDivider(key, "_", upper); 225 | } 226 | 227 | /**ABCdEfg => upper ? A$B$CD$EFG : a$b$cd$efg 228 | * @param key 229 | * @return 230 | */ 231 | public static String recoverDollar(@NotNull String key, Boolean upper) { 232 | return recoverDivider(key, "$", upper); 233 | } 234 | 235 | /**ABCdEfg => upper ? A.B.CD.EFG : a.b.cd.efg 236 | * @param key 237 | * @return 238 | */ 239 | public static String recoverDot(@NotNull String key, Boolean upper) { 240 | return recoverDivider(key, ".", upper); 241 | } 242 | 243 | /**ABCdEfg => upper ? A_B_CD_EFG : a/b/cd/efg 244 | * @param key 245 | * @return 246 | */ 247 | public static String recoverDivider(@NotNull String key, Boolean upper) { 248 | return recoverDivider(key, "/", upper); 249 | } 250 | 251 | /**驼峰格式转为带分隔符的全大写或全小写格式 252 | * @param key 253 | * @param divider 254 | * @param upper 255 | * @return 256 | */ 257 | public static String recoverDivider(@NotNull String key, @NotNull String divider, Boolean upper) { 258 | StringBuilder name = new StringBuilder(); 259 | char[] cs = key.toCharArray(); 260 | int len = key.length(); 261 | for (int i = 0; i < len; i++) { 262 | String s = key.substring(i, i + 1); 263 | if (i > 0 && PATTERN_ALPHA_BIG.matcher(s).matches()) { 264 | name.append(divider); 265 | } 266 | if (upper != null) { 267 | s = upper ? s.toUpperCase() : s.toLowerCase(); 268 | } 269 | name.append(s); 270 | } 271 | return name.toString(); 272 | } 273 | 274 | 275 | } 276 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/JSONResponse.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson; 7 | 8 | import java.util.*; 9 | 10 | /**parser for response 11 | * @author Lemon 12 | * @see #getObject 13 | * @see #getList 14 | * @use JSONResponse response = new JSONResponse(json); 15 | *
User user = response.getObject(User.class);//not a must 16 | *
List commenntList = response.getList("Comment[]", Comment.class);//not a must 17 | */ 18 | public interface JSONResponse, L extends List> extends JSONMap { 19 | static final String TAG = "JSONResponse"; 20 | 21 | // 节约性能和减少 bug,除了关键词 @key ,一般都符合变量命名规范,不符合也原样返回便于调试 22 | /**格式化带 - 中横线的单词 23 | */ 24 | public static boolean IS_FORMAT_HYPHEN = false; 25 | /**格式化带 _ 下划线的单词 26 | */ 27 | public static boolean IS_FORMAT_UNDERLINE = false; 28 | /**格式化带 $ 美元符的单词 29 | */ 30 | public static boolean IS_FORMAT_DOLLAR = false; 31 | 32 | 33 | //default JSONResponse() { 34 | // super(); 35 | //} 36 | //default JSONResponse(Object json) { 37 | // this(parseObject(json)); 38 | //} 39 | //default JSONResponse(Object json, JSONParser parser) { 40 | // this(parseObject(json, parser)); 41 | //} 42 | //default JSONResponse(Map object) { 43 | // super(format(object)); 44 | //} 45 | //default JSONResponse(M object, JSONCreator creator) { 46 | // super(format(object, creator)); 47 | //} 48 | 49 | //状态信息,非GET请求获得的信息<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 50 | 51 | public static final int CODE_SUCCESS = 200; //成功 52 | public static final int CODE_UNSUPPORTED_ENCODING = 400; //编码错误 53 | public static final int CODE_ILLEGAL_ACCESS = 401; //权限错误 54 | public static final int CODE_UNSUPPORTED_OPERATION = 403; //禁止操作 55 | public static final int CODE_NOT_FOUND = 404; //未找到 56 | public static final int CODE_ILLEGAL_ARGUMENT = 406; //参数错误 57 | public static final int CODE_NOT_LOGGED_IN = 407; //未登录 58 | public static final int CODE_TIME_OUT = 408; //超时 59 | public static final int CODE_CONFLICT = 409; //重复,已存在 60 | public static final int CODE_CONDITION_ERROR = 412; //条件错误,如密码错误 61 | public static final int CODE_UNSUPPORTED_TYPE = 415; //类型错误 62 | public static final int CODE_OUT_OF_RANGE = 416; //超出范围 63 | public static final int CODE_NULL_POINTER = 417; //对象为空 64 | public static final int CODE_SERVER_ERROR = 500; //服务器内部错误 65 | 66 | 67 | public static final String MSG_SUCCEED = "success"; //成功 68 | public static final String MSG_SERVER_ERROR = "Internal Server Error!"; //服务器内部错误 69 | 70 | 71 | public static String KEY_OK = "ok"; 72 | public static String KEY_CODE = "code"; 73 | public static String KEY_MSG = "msg"; 74 | public static final String KEY_COUNT = "count"; 75 | public static final String KEY_TOTAL = "total"; 76 | public static final String KEY_INFO = "info"; //详细的分页信息 77 | public static final String KEY_FIRST = "first"; //是否为首页 78 | public static final String KEY_LAST = "last"; //是否为尾页 79 | public static final String KEY_MAX = "max"; //最大页码 80 | public static final String KEY_MORE = "more"; //是否有更多 81 | 82 | /**获取状态 83 | * @return 84 | */ 85 | default int getCode() { 86 | try { 87 | return JSON.getIntValue(this, KEY_CODE); 88 | } catch (Exception e) { 89 | //empty 90 | } 91 | return 0; 92 | } 93 | /**获取状态 94 | * @return 95 | */ 96 | public static int getCode(Map reponse) { 97 | try { 98 | return JSON.getIntValue(reponse, KEY_CODE); 99 | } catch (Exception e) { 100 | //empty 101 | } 102 | return 0; 103 | } 104 | /**获取状态描述 105 | * @return 106 | */ 107 | default String getMsg() { 108 | return JSON.getString(this, KEY_MSG); 109 | } 110 | /**获取状态描述 111 | * @param response 112 | * @return 113 | */ 114 | public static String getMsg(Map response) { 115 | return response == null ? null : JSON.getString(response, KEY_MSG); 116 | } 117 | /**获取id 118 | * @return 119 | */ 120 | default long getId() { 121 | try { 122 | return JSON.getLongValue(this, KEY_ID); 123 | } catch (Exception e) { 124 | //empty 125 | } 126 | return 0; 127 | } 128 | /**获取数量 129 | * @return 130 | */ 131 | default int getCount() { 132 | try { 133 | return JSON.getIntValue(this, KEY_COUNT); 134 | } catch (Exception e) { 135 | //empty 136 | } 137 | return 0; 138 | } 139 | /**获取总数 140 | * @return 141 | */ 142 | default int getTotal() { 143 | try { 144 | return JSON.getIntValue(this, KEY_TOTAL); 145 | } catch (Exception e) { 146 | //empty 147 | } 148 | return 0; 149 | } 150 | 151 | 152 | /**是否成功 153 | * @return 154 | */ 155 | default boolean isSuccess() { 156 | return isSuccess(getCode()); 157 | } 158 | /**是否成功 159 | * @param code 160 | * @return 161 | */ 162 | public static boolean isSuccess(int code) { 163 | return code == CODE_SUCCESS; 164 | } 165 | /**是否成功 166 | * @param response 167 | * @return 168 | */ 169 | public static boolean isSuccess(JSONResponse response) { 170 | return response != null && response.isSuccess(); 171 | } 172 | /**是否成功 173 | * @param response 174 | * @return 175 | */ 176 | public static boolean isSuccess(Map response) { 177 | return response != null && isSuccess(JSON.getIntValue(response, KEY_CODE)); 178 | } 179 | 180 | /**校验服务端是否存在table 181 | * @return 182 | */ 183 | default boolean isExist() { 184 | return isExist(getCount()); 185 | } 186 | /**校验服务端是否存在table 187 | * @param count 188 | * @return 189 | */ 190 | public static boolean isExist(int count) { 191 | return count > 0; 192 | } 193 | /**校验服务端是否存在table 194 | * @param response 195 | * @return 196 | */ 197 | public static boolean isExist(JSONResponse response) { 198 | return response != null && response.isExist(); 199 | } 200 | public static boolean isExist(Map response) { 201 | return response != null && isExist(JSON.getIntValue(response, KEY_COUNT)); 202 | } 203 | 204 | /**获取内部的JSONResponse 205 | * @param key 206 | * @return 207 | */ 208 | default JSONResponse getJSONResponse(String key) { 209 | return getObject(key, JSONResponse.class); 210 | } 211 | 212 | //cannot get javaBeanDeserizer 213 | // /**获取内部的JSONResponse 214 | // * @param response 215 | // * @param key 216 | // * @return 217 | // */ 218 | // public static JSONResponse getJSONResponse(JSONRequest response, String key) { 219 | // return response == null ? null : response.getObject(key, JSONResponse.class); 220 | // } 221 | //状态信息,非GET请求获得的信息>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 222 | 223 | 224 | /** 225 | * key = clazz.getSimpleName() 226 | * @param clazz 227 | * @return 228 | */ 229 | default T getObject(Class clazz) { 230 | return getObject(clazz == null ? "" : clazz.getSimpleName(), clazz); 231 | } 232 | /** 233 | * @param key 234 | * @param clazz 235 | * @return 236 | */ 237 | default T getObject(String key, Class clazz) { 238 | return getObject(this, key, clazz); 239 | } 240 | /** 241 | * @param object 242 | * @param key 243 | * @param clazz 244 | * @return 245 | */ 246 | public static T getObject( 247 | Map object, String key, Class clazz) { 248 | return toObject(object == null ? null : JSON.get(object, formatObjectKey(key)), clazz); 249 | } 250 | 251 | /** 252 | * @param clazz 253 | * @return 254 | */ 255 | default T toObject(Class clazz) { 256 | return toObject(this, clazz); 257 | } 258 | 259 | /** 260 | * @param object 261 | * @param clazz 262 | * @return 263 | */ 264 | public static , L extends List> T toObject( 265 | Map object, Class clazz) { 266 | return JSON.parseObject(object, clazz); 267 | } 268 | 269 | 270 | 271 | /** 272 | * arrayObject = this 273 | * @param key 274 | * @return 275 | */ 276 | default List getList(String key) { 277 | return JSON.getList(this, key); 278 | } 279 | 280 | /** 281 | * key = KEY_ARRAY 282 | * @param object 283 | * @return 284 | */ 285 | public static List getList(Map object) { 286 | return JSON.getList(object, KEY_ARRAY); 287 | } 288 | /** 289 | * @param object 290 | * @param key 291 | * @param clazz 292 | * @return 293 | */ 294 | public static > List getList(Map object, String key, Class clazz) { 295 | return object == null ? null : JSON.parseArray(JSON.getString(object, formatArrayKey(key)), clazz); 296 | } 297 | 298 | /** 299 | * key = KEY_ARRAY 300 | * @return 301 | */ 302 | default > L getArray() { 303 | return getArray(KEY_ARRAY); 304 | } 305 | /** 306 | * @param key 307 | * @return 308 | */ 309 | default > L getArray(String key) { 310 | return getArray(this, key); 311 | } 312 | /** 313 | * @param object 314 | * @return 315 | */ 316 | public static > L getArray(Map object) { 317 | return getArray(object, KEY_ARRAY); 318 | } 319 | /** 320 | * key = KEY_ARRAY 321 | * @param object 322 | * @param key 323 | * @return 324 | */ 325 | public static > L getArray(Map object, String key) { 326 | return object == null ? null : JSON.get(object, formatArrayKey(key)); 327 | } 328 | 329 | 330 | // /** 331 | // * @return 332 | // */ 333 | // default JSONRequest format() { 334 | // return format(this); 335 | // } 336 | /**格式化key名称 337 | * @param object 338 | * @return 339 | */ 340 | public static , L extends List> M format(final M object) { 341 | //太长查看不方便,不如debug Log.i(TAG, "format object = \n" + JSON.toJSONString(object)); 342 | if (object == null || object.isEmpty()) { 343 | Log.i(TAG, "format object == null || object.isEmpty() >> return object;"); 344 | return object; 345 | } 346 | 347 | M formatedObject = JSON.createJSONObject(); 348 | 349 | Set set = object.keySet(); 350 | if (set != null) { 351 | 352 | Object value; 353 | for (String key : set) { 354 | value = object.get(key); 355 | 356 | if (value instanceof List) {//JSONList,遍历来format内部项 357 | formatedObject.put(formatArrayKey(key), format((L) value)); 358 | } 359 | else if (value instanceof Map) {//JSONRequest,往下一级提取 360 | formatedObject.put(formatObjectKey(key), format((M) value)); 361 | } 362 | else {//其它Object,直接填充 363 | formatedObject.put(formatOtherKey(key), value); 364 | } 365 | } 366 | } 367 | 368 | //太长查看不方便,不如debug Log.i(TAG, "format return formatedObject = " + JSON.toJSONString(formatedObject)); 369 | return formatedObject; 370 | } 371 | 372 | /**格式化key名称 373 | * @param array 374 | * @return 375 | */ 376 | public static , L extends List> L format(final L array) { 377 | //太长查看不方便,不如debug Log.i(TAG, "format array = \n" + JSON.toJSONString(array)); 378 | if (array == null || array.isEmpty()) { 379 | Log.i(TAG, "format array == null || array.isEmpty() >> return array;"); 380 | return array; 381 | } 382 | L formattedArray = JSON.createJSONArray(); 383 | 384 | Object value; 385 | for (int i = 0; i < array.size(); i++) { 386 | value = array.get(i); 387 | if (value instanceof List) {//JSONList,遍历来format内部项 388 | formattedArray.add(format((L) value)); 389 | } 390 | else if (value instanceof Map) {//JSONRequest,往下一级提取 391 | formattedArray.add(format((M) value)); 392 | } 393 | else {//其它Object,直接填充 394 | formattedArray.add(value); 395 | } 396 | } 397 | 398 | //太长查看不方便,不如debug Log.i(TAG, "format return formattedArray = " + JSON.toJSONString(formattedArray)); 399 | return formattedArray; 400 | } 401 | 402 | 403 | /**获取表名称 404 | * @param fullName name 或 name:alias 405 | * @return name => name; name:alias => alias 406 | */ 407 | public static String getTableName(String fullName) { 408 | //key:alias -> alias; key:alias[] -> alias[] 409 | int index = fullName == null ? -1 : fullName.indexOf(":"); 410 | return index < 0 ? fullName : fullName.substring(0, index); 411 | } 412 | 413 | /**获取变量名 414 | * @param fullName 415 | * @return {@link #formatKey(String, boolean, boolean, boolean, boolean, boolean, Boolean)} formatColon = true, formatAt = true, formatHyphen = true, firstCase = true 416 | */ 417 | public static String getVariableName(String fullName) { 418 | if (JSONMap.isArrayKey(fullName)) { 419 | fullName = StringUtil.addSuffix(fullName.substring(0, fullName.length() - 2), "list"); 420 | } 421 | return formatKey(fullName, true, true, true, true, false, true); 422 | } 423 | 424 | /**格式化数组的名称 key[] => keyList; key:alias[] => aliasList; Table-column[] => tableColumnList 425 | * @param key empty ? "list" : key + "List" 且首字母小写 426 | * @return {@link #formatKey(String, boolean, boolean, boolean, boolean, boolean, Boolean)} formatColon = false, formatAt = true, formatHyphen = true, firstCase = true 427 | */ 428 | public static String formatArrayKey(String key) { 429 | if (JSONMap.isArrayKey(key)) { 430 | key = StringUtil.addSuffix(key.substring(0, key.length() - 2), "list"); 431 | } 432 | int index = key == null ? -1 : key.indexOf(":"); 433 | if (index >= 0) { 434 | return key.substring(index + 1); //不处理自定义的 435 | } 436 | 437 | return formatKey(key, false, true, true, IS_FORMAT_UNDERLINE, IS_FORMAT_DOLLAR, false); //节约性能,除了数组对象 Table-column:alias[] ,一般都符合变量命名规范 438 | } 439 | 440 | /**格式化对象的名称 name => name; name:alias => alias 441 | * @param key name 或 name:alias 442 | * @return {@link #formatKey(String, boolean, boolean, boolean, boolean, boolean, Boolean)} formatColon = false, formatAt = true, formatHyphen = false, firstCase = true 443 | */ 444 | public static String formatObjectKey(String key) { 445 | int index = key == null ? -1 : key.indexOf(":"); 446 | if (index >= 0) { 447 | return key.substring(index + 1); // 不处理自定义的 448 | } 449 | 450 | return formatKey(key, false, true, IS_FORMAT_HYPHEN, IS_FORMAT_UNDERLINE, IS_FORMAT_DOLLAR, false); //节约性能,除了表对象 Table:alias ,一般都符合变量命名规范 451 | } 452 | 453 | /**格式化普通值的名称 name => name; name:alias => alias 454 | * @param fullName name 或 name:alias 455 | * @return {@link #formatKey(String, boolean, boolean, boolean, boolean, boolean, Boolean)} formatColon = false, formatAt = true, formatHyphen = false, firstCase = false 456 | */ 457 | public static String formatOtherKey(String fullName) { 458 | return formatKey(fullName, false, true, IS_FORMAT_HYPHEN, IS_FORMAT_UNDERLINE, IS_FORMAT_DOLLAR 459 | , IS_FORMAT_HYPHEN || IS_FORMAT_UNDERLINE || IS_FORMAT_DOLLAR ? false : null); 460 | } 461 | 462 | 463 | /**格式化名称 464 | * @param fullName name 或 name:alias 465 | * @param formatAt 去除前缀 @ , @a => a 466 | * @param formatColon 去除分隔符 : , A:b => b 467 | * @param formatHyphen 去除分隔符 - , A-b-cd-Efg => aBCdEfg 468 | * @param formatUnderline 去除分隔符 _ , A_b_cd_Efg => aBCdEfg 469 | * @param formatDollar 去除分隔符 $ , A$b$cd$Efg => aBCdEfg 470 | * @param firstCase 第一个单词首字母小写,后面的首字母大写, Ab => ab ; A-b-Cd => aBCd 471 | * @return name => name; name:alias => alias 472 | */ 473 | public static String formatKey(String fullName, boolean formatColon, boolean formatAt, boolean formatHyphen 474 | , boolean formatUnderline, boolean formatDollar, Boolean firstCase) { 475 | if (fullName == null) { 476 | Log.w(TAG, "formatKey fullName == null >> return null;"); 477 | return null; 478 | } 479 | 480 | if (formatColon) { 481 | fullName = formatColon(fullName); 482 | } 483 | if (formatAt) { //关键词只去掉前缀,不格式化单词,例如 @a-b 返回 a-b ,最后不会调用 setter 484 | fullName = formatAt(fullName); 485 | } 486 | if (formatHyphen && fullName.contains("-")) { 487 | fullName = formatHyphen(fullName, true); 488 | } 489 | if (formatUnderline && fullName.contains("_")) { 490 | fullName = formatUnderline(fullName, true); 491 | } 492 | if (formatDollar && fullName.contains("$")) { 493 | fullName = formatDollar(fullName, true); 494 | } 495 | 496 | // 默认不格式化普通 key:value (value 不为 [], {}) 的 key 497 | return firstCase == null ? fullName : StringUtil.firstCase(fullName, firstCase); 498 | } 499 | 500 | /**"@key" => "key" 501 | * @param key 502 | * @return 503 | */ 504 | public static String formatAt(@NotNull String key) { 505 | return key.startsWith("@") ? key.substring(1) : key; 506 | } 507 | 508 | /**key:alias => alias 509 | * @param key 510 | * @return 511 | */ 512 | public static String formatColon(@NotNull String key) { 513 | int index = key.indexOf(":"); 514 | return index < 0 ? key : key.substring(index + 1); 515 | } 516 | 517 | /**A-b-cd-Efg => ABCdEfg 518 | * @param key 519 | * @return 520 | */ 521 | public static String formatHyphen(@NotNull String key) { 522 | return StringUtil.firstCase(formatHyphen(key, true), false); 523 | } 524 | /**A-b-cd-Efg => ABCdEfg 525 | * @param key 526 | * @param firstCase 首字符的大小写,true-大写,false-小写,null-不处理 527 | * @return 528 | */ 529 | public static String formatHyphen(@NotNull String key, Boolean firstCase) { 530 | return formatHyphen(key, firstCase, false); 531 | } 532 | /**A-b-cd-Efg => ABCdEfg 533 | * @param key 534 | * @param firstCase 首字符的大小写,true-大写,false-小写,null-不处理 535 | * @param otherCase 非首字符的大小写,true-大写,false-小写,null-不处理 536 | * @return 537 | */ 538 | public static String formatHyphen(@NotNull String key, Boolean firstCase, Boolean otherCase) { 539 | return formatDivider(key, "-", firstCase, otherCase); 540 | } 541 | 542 | /**A_b_cd_Efg => ABCdEfg 543 | * @param key 544 | * @return 545 | */ 546 | public static String formatUnderline(@NotNull String key) { 547 | return StringUtil.firstCase(formatUnderline(key, true), false); 548 | } 549 | /**A_b_cd_Efg => ABCdEfg 550 | * @param key 551 | * @param firstCase 首字符的大小写,true-大写,false-小写,null-不处理 552 | * @return 553 | */ 554 | public static String formatUnderline(@NotNull String key, Boolean firstCase) { 555 | return formatUnderline(key, firstCase, false); 556 | } 557 | /**A_b_cd_Efg => ABCdEfg 558 | * @param key 559 | * @param firstCase 首字符的大小写,true-大写,false-小写,null-不处理 560 | * @param otherCase 非首字符的大小写,true-大写,false-小写,null-不处理 561 | * @return 562 | */ 563 | public static String formatUnderline(@NotNull String key, Boolean firstCase, Boolean otherCase) { 564 | return formatDivider(key, "_", firstCase, otherCase); 565 | } 566 | 567 | /**A$b$cd$Efg => ABCdEfg 568 | * @param key 569 | * @return 570 | */ 571 | public static String formatDollar(@NotNull String key) { 572 | return StringUtil.firstCase(formatDollar(key, true), false); 573 | } 574 | /**A$b$cd$Efg => ABCdEfg 575 | * @param key 576 | * @param firstCase 首字符的大小写,true-大写,false-小写,null-不处理 577 | * @return 578 | */ 579 | public static String formatDollar(@NotNull String key, Boolean firstCase) { 580 | return formatDollar(key, firstCase, false); 581 | } 582 | /**A$b$cd$Efg => ABCdEfg 583 | * @param key 584 | * @param firstCase 首字符的大小写,true-大写,false-小写,null-不处理 585 | * @param otherCase 非首字符的大小写,true-大写,false-小写,null-不处理 586 | * @return 587 | */ 588 | public static String formatDollar(@NotNull String key, Boolean firstCase, Boolean otherCase) { 589 | return formatDivider(key, "$", firstCase, otherCase); 590 | } 591 | 592 | /**A.b.cd.Efg => ABCdEfg 593 | * @param key 594 | * @return 595 | */ 596 | public static String formatDot(@NotNull String key) { 597 | return StringUtil.firstCase(formatDot(key, true), false); 598 | } 599 | /**A.b.cd.Efg => ABCdEfg 600 | * @param key 601 | * @param firstCase 首字符的大小写,true-大写,false-小写,null-不处理 602 | * @return 603 | */ 604 | public static String formatDot(@NotNull String key, Boolean firstCase) { 605 | return formatDot(key, firstCase, false); 606 | } 607 | /**A.b.cd.Efg => ABCdEfg 608 | * @param key 609 | * @param firstCase 首字符的大小写,true-大写,false-小写,null-不处理 610 | * @param otherCase 非首字符的大小写,true-大写,false-小写,null-不处理 611 | * @return 612 | */ 613 | public static String formatDot(@NotNull String key, Boolean firstCase, Boolean otherCase) { 614 | return formatDivider(key, ".", firstCase, otherCase); 615 | } 616 | 617 | /**A/b/cd/Efg => ABCdEfg 618 | * @param key 619 | * @return 620 | */ 621 | public static String formatDivider(@NotNull String key, Boolean firstCase) { 622 | return formatDivider(key, "/", firstCase); 623 | } 624 | 625 | /**去除分割符,返回驼峰格式 626 | * @param key 627 | * @param divider 628 | * @return 629 | */ 630 | public static String formatDivider(@NotNull String key, @NotNull String divider) { 631 | return StringUtil.firstCase(formatDivider(key, divider, true), false); 632 | } 633 | /**去除分割符,返回驼峰格式 634 | * @param key 635 | * @param divider 636 | * @param firstCase 首字符的大小写,true-大写,false-小写,null-不处理 637 | * @return 638 | */ 639 | public static String formatDivider(@NotNull String key, @NotNull String divider, Boolean firstCase) { 640 | return formatDivider(key, divider, firstCase, false); 641 | } 642 | 643 | /**去除分割符,返回驼峰格式 644 | * @param key 645 | * @param divider 646 | * @param firstCase 首字符的大小写,true-大写,false-小写,null-不处理 647 | * @param otherCase 非首字符的大小写,true-大写,false-小写,null-不处理 648 | * @return 649 | */ 650 | public static String formatDivider(@NotNull String key, @NotNull String divider, Boolean firstCase, Boolean otherCase) { 651 | String[] parts = StringUtil.split(key, divider); 652 | StringBuilder name = new StringBuilder(); 653 | for (String part : parts) { 654 | if (otherCase != null) { 655 | part = otherCase ? part.toUpperCase() : part.toLowerCase(); 656 | } 657 | if (firstCase != null) { 658 | part = StringUtil.firstCase(part, firstCase); 659 | } 660 | name.append(part); 661 | } 662 | return name.toString(); 663 | } 664 | 665 | } 666 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/Log.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson; 7 | 8 | import java.text.SimpleDateFormat; 9 | 10 | /**测试用Log 11 | * @modifier Lemon 12 | */ 13 | public class Log { 14 | 15 | public static boolean DEBUG = true; 16 | 17 | public static final String VERSION = "8.0.0"; 18 | public static final String KEY_SYSTEM_INFO_DIVIDER = "\n---|-----APIJSON SYSTEM INFO-----|---\n"; 19 | 20 | public static final String OS_NAME; 21 | public static final String OS_VERSION; 22 | public static final String OS_ARCH; 23 | public static final String JAVA_VERSION; 24 | static { 25 | OS_NAME = System.getProperty("os.name"); 26 | OS_VERSION = System.getProperty("os.version"); 27 | OS_ARCH = System.getProperty("os.arch"); 28 | JAVA_VERSION = System.getProperty("java.version"); 29 | } 30 | 31 | 32 | //默认的时间格式 33 | public static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS"); 34 | 35 | /** 36 | * modify date format 37 | * @param dateFormatString 38 | */ 39 | public static void setDateFormat(String dateFormatString) { 40 | DATE_FORMAT = new SimpleDateFormat(dateFormatString); 41 | } 42 | 43 | /** 44 | * log info by level tag and msg 45 | * @param TAG 46 | * @param msg 47 | * @param level 48 | */ 49 | public static void logInfo(String TAG, String msg, String level){ 50 | if(level.equals("DEBUG") || level .equals("ERROR") ||level.equals("WARN")){ 51 | System.err.println(DATE_FORMAT.format(System.currentTimeMillis()) + ": " + TAG + "." + level + ": " + msg); 52 | } 53 | else if(level.equals("VERBOSE") || level .equals("INFO") ){ 54 | System.out.println(DATE_FORMAT.format(System.currentTimeMillis()) + ": " + TAG + "." + level + ": " + msg); 55 | } 56 | } 57 | 58 | 59 | /** 60 | * @param TAG 61 | * @param msg 62 | */ 63 | public static void d(String TAG, String msg) { 64 | if (DEBUG) { 65 | logInfo(TAG,msg,"DEBUG"); 66 | } 67 | } 68 | 69 | /** 70 | * Forced debug 71 | * @param TAG tag 72 | * @param msg debug messages 73 | */ 74 | public static void fd(String TAG, String msg) { 75 | logInfo(TAG,msg,"DEBUG"); 76 | } 77 | 78 | /** 79 | * Generate separation line 80 | * @param pre prefix 81 | * @param symbol used for generating separation line 82 | * @param post postfix 83 | */ 84 | public static void sl(String pre,char symbol ,String post) { 85 | System.err.println(pre+new String(new char[48]).replace('\u0000', symbol)+post); 86 | } 87 | 88 | /** 89 | * @param TAG 90 | * @param msg 91 | */ 92 | public static void v(String TAG, String msg) { 93 | if (DEBUG) { 94 | logInfo(TAG,msg,"VERBOSE"); 95 | } 96 | } 97 | 98 | /** 99 | * @param TAG 100 | * @param msg 101 | */ 102 | public static void i(String TAG, String msg) { 103 | if (DEBUG) { 104 | logInfo(TAG,msg,"INFO"); 105 | } 106 | } 107 | 108 | /** 109 | * @param TAG 110 | * @param msg 111 | */ 112 | public static void e(String TAG, String msg) { 113 | if (DEBUG) { 114 | logInfo(TAG,msg,"ERROR"); 115 | } 116 | } 117 | 118 | /** 119 | * @param TAG 120 | * @param msg 121 | */ 122 | public static void w(String TAG, String msg) { 123 | if (DEBUG) { 124 | logInfo(TAG,msg,"WARN"); 125 | } 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/MethodAccess.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson; 7 | 8 | import java.lang.annotation.Documented; 9 | import java.lang.annotation.Inherited; 10 | import java.lang.annotation.Retention; 11 | import java.lang.annotation.Target; 12 | 13 | import static apijson.orm.AbstractVerifier.ADMIN; 14 | import static apijson.orm.AbstractVerifier.CIRCLE; 15 | import static apijson.orm.AbstractVerifier.CONTACT; 16 | import static apijson.orm.AbstractVerifier.LOGIN; 17 | import static apijson.orm.AbstractVerifier.OWNER; 18 | import static apijson.orm.AbstractVerifier.UNKNOWN; 19 | import static java.lang.annotation.ElementType.TYPE; 20 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 21 | 22 | /**请求方法权限,只允许某些角色通过对应方法访问 23 | * @author Lemon 24 | */ 25 | @Documented 26 | @Retention(RUNTIME) 27 | @Target(TYPE) 28 | @Inherited 29 | public @interface MethodAccess { 30 | 31 | /**@see {@link RequestMethod#GET} 32 | * @return 该请求方法允许的角色 default {UNKNOWN, LOGIN, CONTACT, CIRCLE, OWNER, ADMIN}; 33 | */ 34 | String[] GET() default {UNKNOWN, LOGIN, CONTACT, CIRCLE, OWNER, ADMIN}; 35 | 36 | /**@see {@link RequestMethod#HEAD} 37 | * @return 该请求方法允许的角色 default {UNKNOWN, LOGIN, CONTACT, CIRCLE, OWNER, ADMIN}; 38 | */ 39 | String[] HEAD() default {UNKNOWN, LOGIN, CONTACT, CIRCLE, OWNER, ADMIN}; 40 | 41 | /**@see {@link RequestMethod#GETS} 42 | * @return 该请求方法允许的角色 default {LOGIN, CONTACT, CIRCLE, OWNER, ADMIN}; 43 | */ 44 | String[] GETS() default {LOGIN, CONTACT, CIRCLE, OWNER, ADMIN}; 45 | 46 | /**@see {@link RequestMethod#HEADS} 47 | * @return 该请求方法允许的角色 default {LOGIN, CONTACT, CIRCLE, OWNER, ADMIN}; 48 | */ 49 | String[] HEADS() default {LOGIN, CONTACT, CIRCLE, OWNER, ADMIN}; 50 | 51 | /**@see {@link RequestMethod#POST} 52 | * @return 该请求方法允许的角色 default {LOGIN, ADMIN}; 53 | */ 54 | String[] POST() default {OWNER, ADMIN}; 55 | 56 | /**@see {@link RequestMethod#PUT} 57 | * @return 该请求方法允许的角色 default {OWNER, ADMIN}; 58 | */ 59 | String[] PUT() default {OWNER, ADMIN}; 60 | 61 | /**@see {@link RequestMethod#DELETE} 62 | * @return 该请求方法允许的角色 default {OWNER, ADMIN}; 63 | */ 64 | String[] DELETE() default {OWNER, ADMIN}; 65 | 66 | } 67 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/NotNull.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson; 7 | 8 | import java.lang.annotation.Documented; 9 | import java.lang.annotation.Retention; 10 | import java.lang.annotation.Target; 11 | 12 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 13 | import static java.lang.annotation.ElementType.CONSTRUCTOR; 14 | import static java.lang.annotation.ElementType.FIELD; 15 | import static java.lang.annotation.ElementType.METHOD; 16 | import static java.lang.annotation.ElementType.PARAMETER; 17 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 18 | 19 | 20 | /**非null注解 21 | * javax.validation.constraints.NotNull不在JDK里面,为了减少第三方库引用就在这里实现了一个替代品 22 | * @author Lemon 23 | */ 24 | @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) 25 | @Retention(RUNTIME) 26 | @Documented 27 | public @interface NotNull { 28 | } 29 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/RequestMethod.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson; 7 | 8 | import java.util.Arrays; 9 | import java.util.List; 10 | 11 | /**请求方法,对应org.springframework.web.bind.annotation.RequestMethod,多出GETS,HEADS方法 12 | * @author Lemon 13 | */ 14 | public enum RequestMethod { 15 | 16 | /** 17 | * 常规获取数据方式 18 | */ 19 | GET, 20 | 21 | /** 22 | * 检查,默认是非空检查,返回数据总数 23 | */ 24 | HEAD, 25 | 26 | /**Safe, Single, Simple 27 | *
限制性GET,通过POST来GET数据,不显示请求内容和返回结果,并且校验请求,一般用于对安全要求比较高的请求 28 | */ 29 | GETS, 30 | 31 | /**Safe, Single, Simple 32 | *
限制性HEAD,通过POST来HEAD数据,不显示请求内容和返回结果,并且校验请求,一般用于对安全要求比较高的请求 33 | */ 34 | HEADS, 35 | 36 | /** 37 | * 新增(或者说插入)数据 38 | */ 39 | POST, 40 | 41 | /** 42 | * 修改数据,只修改传入字段对应的值 43 | */ 44 | PUT, 45 | 46 | /** 47 | * 删除数据 48 | */ 49 | DELETE, 50 | 51 | /** 52 | * json 包含多条语句,支持增删改查、函数调用 53 | */ 54 | CRUD; 55 | 56 | public static final RequestMethod[] ALL = new RequestMethod[]{ GET, HEAD, GETS, HEADS, POST, PUT, DELETE, CRUD }; 57 | public static final List ALL_NAME_LIST = Arrays.asList( 58 | GET.name(), HEAD.name(), GETS.name(), HEADS.name(), POST.name(), PUT.name(), DELETE.name(), CRUD.name() 59 | ); 60 | 61 | /**是否为GET请求方法 62 | * @param method 63 | * @param containPrivate 包含私密(非明文)获取方法GETS 64 | * @return 65 | */ 66 | public static boolean isGetMethod(RequestMethod method, boolean containPrivate) { 67 | return method == null || method == GET || (containPrivate && method == GETS); 68 | } 69 | 70 | /**是否为HEAD请求方法 71 | * @param method 72 | * @param containPrivate 包含私密(非明文)获取方法HEADS 73 | * @return 74 | */ 75 | public static boolean isHeadMethod(RequestMethod method, boolean containPrivate) { 76 | return method == HEAD || (containPrivate && method == HEADS); 77 | } 78 | 79 | /**是否为查询的请求方法 80 | * @param method 81 | * @return 读操作(GET型或HEAD型) - true, 写操作(POST,PUT,DELETE) - false 82 | */ 83 | public static boolean isQueryMethod(RequestMethod method) { 84 | return isGetMethod(method, true) || isHeadMethod(method, true); 85 | } 86 | 87 | /**是否为更新(增删改)的请求方法 88 | * @param method 89 | * @return 读操作(GET型或HEAD型) - false, 写操作(POST,PUT,DELETE) - true 90 | */ 91 | public static boolean isUpdateMethod(RequestMethod method) { 92 | return ! isQueryMethod(method); 93 | } 94 | 95 | /**是否为开放(不限制请求的结构或内容;明文,浏览器能直接访问及查看)的请求方法 96 | * @param method 97 | * @return 98 | */ 99 | public static boolean isPublicMethod(RequestMethod method) { 100 | return method == null || method == GET || method == HEAD; 101 | } 102 | 103 | /**是否为私有(限制请求的结构或内容)的请求方法 104 | * @param method 105 | * @return 106 | */ 107 | public static boolean isPrivateMethod(RequestMethod method) { 108 | return ! isPublicMethod(method); 109 | } 110 | 111 | public static String getName(RequestMethod method) { 112 | return method == null ? GET.name() : method.name(); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/SQL.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson; 7 | 8 | /**SQL语句,函数名尽量和JDK中相同或类似功能的函数的名称一致 9 | * @author Lemon 10 | */ 11 | public class SQL { 12 | 13 | public static final String JOIN = " JOIN "; 14 | public static final String ON = " ON "; 15 | public static final String OR = " OR "; 16 | public static final String AND = " AND "; 17 | public static final String NOT = " NOT "; 18 | public static final String AS = " AS "; 19 | public static final String IS = " IS "; 20 | public static final String NULL = " NULL "; 21 | public static final String IS_NOT = " IS NOT "; 22 | public static final String IS_NULL = " IS NULL "; 23 | public static final String IS_NOT_NULL = " IS NOT NULL "; 24 | 25 | //括号必须紧跟函数名! count (...) 报错! 26 | public static final String COUNT = "count"; 27 | public static final String SUM = "sum"; 28 | public static final String MAX = "max"; 29 | public static final String MIN = "min"; 30 | public static final String AVG = "avg"; 31 | 32 | /** 33 | * isNull = true 34 | * @return {@link #isNull(boolean)} 35 | */ 36 | public static String isNull() { 37 | return isNull(true); 38 | } 39 | /** 40 | * @param isNull 41 | * @return {@link #IS} + (isNull ? "" : {@link #NOT}) + {@link #NULL}; 42 | */ 43 | public static String isNull(boolean isNull) { 44 | return IS + (isNull ? "" : NOT) + NULL; 45 | } 46 | /** 47 | * isNull = true 48 | * @param s 49 | * @return {@link #isNull(String, boolean)} 50 | */ 51 | public static String isNull(String s) { 52 | return isNull(s, true); 53 | } 54 | /** 55 | * @param s 56 | * @param isNull 57 | * @return s + {@link #isNull(boolean)} 58 | */ 59 | public static String isNull(String s, boolean isNull) { 60 | return s + isNull(isNull); 61 | } 62 | 63 | /** 64 | * isEmpty = true 65 | * @param s 66 | * @return {@link #isEmpty(String, boolean)} 67 | */ 68 | public static String isEmpty(String s) { 69 | return isEmpty(s, true); 70 | } 71 | /** 72 | * trim = false 73 | * @param s 74 | * @param isEmpty 75 | * @return {@link #isEmpty(String, boolean, boolean)} 76 | */ 77 | public static String isEmpty(String s, boolean isEmpty) { 78 | return isEmpty(s, isEmpty, false); 79 | } 80 | /** 81 | * nullable = true 82 | * @param s 83 | * @param isEmpty <=0 84 | * @param trim s = trim(s); 85 | * @return {@link #isEmpty(String, boolean, boolean, boolean)} 86 | */ 87 | public static String isEmpty(String s, boolean isEmpty, boolean trim) { 88 | return isEmpty(s, isEmpty, trim, true); 89 | } 90 | /** 91 | * @param s 92 | * @param isEmpty <=0 93 | * @param trim s = trim(s); 94 | * @param nullable isNull(s, true) + {@link #OR} + 95 | * @return {@link #lengthCompare(String, String)} 96 | */ 97 | public static String isEmpty(String s, boolean isEmpty, boolean trim, boolean nullable) { 98 | if (trim) { 99 | s = trim(s); 100 | } 101 | return (nullable ? isNull(s, true) + OR : "") + lengthCompare(s, (isEmpty ? "<=" : ">") + "0"); 102 | } 103 | /** 104 | * @param s 因为POWER(x,y)等函数含有不只一个key,所以需要客户端添加进去,服务端检测到条件中有'('和')'时就不转换,直接当SQL语句查询 105 | * @return {@link #length(String)} + compare 106 | */ 107 | public static String lengthCompare(String s, String compare) { 108 | return length(s) + compare; 109 | } 110 | 111 | 112 | /** 113 | * @param s 因为POWER(x,y)等函数含有不只一个key,所以需要客户端添加进去,服务端检测到条件中有'('和')'时就不转换,直接当SQL语句查询 114 | * @return "length(" + s + ")" 115 | */ 116 | public static String length(String s) { 117 | return "length(" + s + ")"; 118 | } 119 | /** 120 | * @param s 因为POWER(x,y)等函数含有不只一个key,所以需要客户端添加进去,服务端检测到条件中有'('和')'时就不转换,直接当SQL语句查询 121 | * @return "json_length(" + s + ")" 122 | */ 123 | public static String json_length(String s) { 124 | return "json_length(" + s + ")"; 125 | } 126 | /** 127 | * @param s 因为POWER(x,y)等函数含有不只一个key,所以需要客户端添加进去,服务端检测到条件中有'('和')'时就不转换,直接当SQL语句查询 128 | * @return "char_length(" + s + ")" 129 | */ 130 | public static String charLength(String s) { 131 | return "char_length(" + s + ")"; 132 | } 133 | 134 | /** 135 | * @param s 136 | * @return "trim(" + s + ")" 137 | */ 138 | public static String trim(String s) { 139 | return "trim(" + s + ")"; 140 | } 141 | /** 142 | * @param s 143 | * @return "ltrim(" + s + ")" 144 | */ 145 | public static String trimLeft(String s) { 146 | return "ltrim(" + s + ")"; 147 | } 148 | /** 149 | * @param s 150 | * @return "rtrim(" + s + ")" 151 | */ 152 | public static String trimRight(String s) { 153 | return "rtrim(" + s + ")"; 154 | } 155 | 156 | /** 157 | * @param s 158 | * @param n 159 | * @return "left(" + s + "," + n + ")" 160 | */ 161 | public static String left(String s, int n) { 162 | return "left(" + s + "," + n + ")"; 163 | } 164 | /** 165 | * @param s 166 | * @param n 167 | * @return "right(" + s + "," + n + ")" 168 | */ 169 | public static String right(String s, int n) { 170 | return "right(" + s + "," + n + ")"; 171 | } 172 | 173 | /** 174 | * @param s 175 | * @param start 176 | * @param end 177 | * @return "substring(" + s + "," + start + "," + (end-start) + ")" 178 | */ 179 | public static String subString(String s, int start, int end) { 180 | return "substring(" + s + "," + start + "," + (end-start) + ")"; 181 | } 182 | 183 | /** 184 | * @param s 185 | * @param c 186 | * @return "instr(" + s + ", " + c + ")" 187 | */ 188 | public static String indexOf(String s, String c) { 189 | return "instr(" + s + ", " + c + ")"; 190 | } 191 | 192 | /** 193 | * @param s 194 | * @param c1 195 | * @param c2 196 | * @return "replace(" + s + ", " + c1 + ", " + c2 + ")" 197 | */ 198 | public static String replace(String s, String c1, String c2) { 199 | return "replace(" + s + ", " + c1 + ", " + c2 + ")"; 200 | } 201 | 202 | /** 203 | * @param s1 204 | * @param s2 205 | * @return "concat(" + s1 + ", " + s2 + ")" 206 | */ 207 | public static String concat(String s1, String s2) { 208 | return "concat(" + s1 + ", " + s2 + ")"; 209 | } 210 | 211 | /** 212 | * @param s1 213 | * @param s2 214 | * @return "strcmp(" + s1 + ", " + s2 + ")" 215 | */ 216 | public static String equals(String s1, String s2) { 217 | return "strcmp(" + s1 + ", " + s2 + ")"; 218 | } 219 | 220 | /** 221 | * @param s 222 | * @return "upper(" + s + ")" 223 | */ 224 | public static String toUpperCase(String s) { 225 | return "upper(" + s + ")"; 226 | } 227 | /** 228 | * @param s 229 | * @return "lower(" + s + ")" 230 | */ 231 | public static String toLowerCase(String s) { 232 | return "lower(" + s + ")"; 233 | } 234 | 235 | 236 | 237 | 238 | //column and function<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 239 | 240 | /**字段 241 | * @param column 242 | * @return column.isEmpty() ? "*" : column; 243 | */ 244 | public static String column(String column) { 245 | column = StringUtil.trim(column); 246 | return column.isEmpty() ? "*" : column; 247 | } 248 | /**有别名的字段 249 | * @param column 250 | * @return {@link #count(String)} + {@link #AS}; 251 | */ 252 | public static String columnAs(String column) { 253 | return count(column) + AS; 254 | } 255 | 256 | /**函数 257 | * @param column if (StringUtil.isEmpty(column, true) || column.contains(",")) -> column = null; 258 | * @return " " + fun + "(" + {@link #column(String)} + ") "; 259 | */ 260 | public static String function(String fun, String column) { 261 | // 支持 fun(col1,col2..) 262 | // if (StringUtil.isEmpty(column, true) || column.contains(",")) { 263 | // column = null; //解决 count(id,name) 这种多个字段导致的SQL异常 264 | // } 265 | return " " + fun + "(" + column(column) + ") "; 266 | } 267 | /**有别名的函数 268 | * @param column 269 | * @return {@link #function(String, String)} + {@link #AS} + fun; 270 | */ 271 | public static String functionAs(String fun, String column) { 272 | return function(fun, column) + AS + fun + " "; 273 | } 274 | 275 | /**计数 276 | * column = null 277 | * @return {@link #count(String)} 278 | */ 279 | public static String count() { 280 | return count(null); 281 | } 282 | /**计数 283 | * fun = {@link #COUNT} 284 | * @param column 285 | * @return {@link #functionAs(String, String)} 286 | */ 287 | public static String count(String column) { 288 | return functionAs(COUNT, column); 289 | } 290 | /**求和 291 | * fun = {@link #SUM} 292 | * @param column 293 | * @return {@link #functionAs(String, String)} 294 | */ 295 | public static String sum(String column) { 296 | return functionAs(SUM, column); 297 | } 298 | /**最大值 299 | * fun = {@link #MAX} 300 | * @param column 301 | * @return {@link #functionAs(String, String)} 302 | */ 303 | public static String max(String column) { 304 | return functionAs(MAX, column); 305 | } 306 | /**最小值 307 | * fun = {@link #MIN} 308 | * @param column 309 | * @return {@link #functionAs(String, String)} 310 | */ 311 | public static String min(String column) { 312 | return functionAs(MIN, column); 313 | } 314 | /**平均值 315 | * fun = {@link #AVG} 316 | * @param column 317 | * @return {@link #functionAs(String, String)} 318 | */ 319 | public static String avg(String column) { 320 | return functionAs(AVG, column); 321 | } 322 | 323 | //column and function>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 324 | 325 | 326 | 327 | //search<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 328 | 329 | public static final int SEARCH_TYPE_CONTAIN_FULL = 0; 330 | public static final int SEARCH_TYPE_CONTAIN_ORDER = 1; 331 | public static final int SEARCH_TYPE_CONTAIN_SINGLE = 2; 332 | public static final int SEARCH_TYPE_CONTAIN_ANY = 3; 333 | public static final int SEARCH_TYPE_START = 4; 334 | public static final int SEARCH_TYPE_END = 5; 335 | public static final int SEARCH_TYPE_START_SINGLE = 6; 336 | public static final int SEARCH_TYPE_END_SINGLE = 7; 337 | public static final int SEARCH_TYPE_PART_MATCH = 8; 338 | /**获取搜索值 339 | * @param s 340 | * @return 341 | */ 342 | public static String search(String s) { 343 | return search(s, SEARCH_TYPE_CONTAIN_FULL); 344 | } 345 | /**获取搜索值 346 | * @param s 347 | * @param type 348 | * @return 349 | */ 350 | public static String search(String s, int type) { 351 | return search(s, type, true); 352 | } 353 | /**获取搜索值 354 | * @param s 355 | * @param type 356 | * @param ignoreCase 357 | * @return default SEARCH_TYPE_CONTAIN_FULL 358 | */ 359 | public static String search(String s, int type, boolean ignoreCase) { 360 | if (s == null) { 361 | return null; 362 | } 363 | switch (type) { 364 | case SEARCH_TYPE_CONTAIN_SINGLE: 365 | return "_" + s + "_"; 366 | case SEARCH_TYPE_CONTAIN_ORDER: 367 | char[] cs = s.toCharArray(); 368 | if (cs == null) { 369 | return null; 370 | } 371 | String value = "%"; 372 | for (int i = 0; i < cs.length; i++) { 373 | value += cs[i] + "%"; 374 | } 375 | return value; 376 | case SEARCH_TYPE_START: 377 | return s + "%"; 378 | case SEARCH_TYPE_END: 379 | return "%" + s; 380 | case SEARCH_TYPE_START_SINGLE: 381 | return s + "_"; 382 | case SEARCH_TYPE_END_SINGLE: 383 | return "_" + s; 384 | case SEARCH_TYPE_CONTAIN_ANY: 385 | case SEARCH_TYPE_PART_MATCH: 386 | cs = s.toCharArray(); 387 | if (cs == null) { 388 | return null; 389 | } 390 | value = ""; 391 | for (int i = 0; i < cs.length; i++) { 392 | value += search("" + cs[i], SEARCH_TYPE_CONTAIN_FULL, ignoreCase); 393 | } 394 | return value; 395 | default://SEARCH_TYPE_CONTAIN_FULL 396 | return "%" + s + "%"; 397 | } 398 | } 399 | 400 | //search>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 401 | 402 | 403 | public static boolean isBooleanOrNumber(String type) { 404 | type = StringUtil.toUpperCase(type, true); 405 | return type.isEmpty() || (type.endsWith("INT") && type.endsWith("POINT") == false) 406 | || type.endsWith("BOOLEAN") || type.endsWith("ENUM") 407 | || type.endsWith("FLOAT") || type.endsWith("DOUBLE") || type.endsWith("DECIMAL"); 408 | } 409 | 410 | 411 | } 412 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/Entry.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.util.Map; 9 | 10 | /**自定义Entry 11 | * *java.util.Map.Entry是interface,new Entry(...)不好用,其它的Entry也不好用 12 | * @author Lemon 13 | * @param key 14 | * @param value 15 | * @use new Entry(...) 16 | * @warn K,V都需要基本类型时不建议使用,判空麻烦,不如新建一个Model 17 | */ 18 | public class Entry implements Map.Entry { 19 | 20 | public K key; 21 | public V value; 22 | 23 | public Entry() { 24 | //default 25 | } 26 | public Entry(K key) { 27 | this(key, null); 28 | } 29 | public Entry(K key, V value) { 30 | this.key = key; 31 | this.value = value; 32 | } 33 | 34 | 35 | public K getKey() { 36 | return key; 37 | } 38 | public void setKey(K key) { 39 | this.key = key; 40 | } 41 | public V getValue() { 42 | return value; 43 | } 44 | public V setValue(V value) { 45 | this.value = value; 46 | return value; 47 | } 48 | 49 | public boolean isEmpty() { 50 | return key == null && value == null; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/FunctionParser.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import apijson.*; 12 | 13 | 14 | /**远程函数解析器 15 | * @author Lemon 16 | */ 17 | public interface FunctionParser, L extends List> { 18 | 19 | Object invoke(@NotNull String function, @NotNull M currentObject) throws Exception; 20 | Object invoke(@NotNull String function, @NotNull M currentObject, boolean containRaw) throws Exception; 21 | 22 | Parser getParser(); 23 | 24 | FunctionParser setParser(Parser parser); 25 | 26 | RequestMethod getMethod(); 27 | FunctionParser setMethod(RequestMethod method); 28 | 29 | String getTag(); 30 | FunctionParser setTag(String tag); 31 | 32 | int getVersion(); 33 | FunctionParser setVersion(int version); 34 | 35 | @NotNull 36 | M getRequest(); 37 | FunctionParser setRequest(@NotNull M request); 38 | 39 | 40 | String getKey(); 41 | FunctionParser setKey(String key); 42 | 43 | String getParentPath(); 44 | FunctionParser setParentPath(String parentPath); 45 | 46 | String getCurrentName(); 47 | FunctionParser setCurrentName(String currentName); 48 | 49 | 50 | @NotNull 51 | M getCurrentObject(); 52 | FunctionParser setCurrentObject(@NotNull M currentObject); 53 | 54 | } 55 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/JSONRequest.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.util.*; 9 | 10 | import apijson.JSON; 11 | import apijson.StringUtil; 12 | 13 | /**JSONRequest for Server to replace apijson.JSONMap, 14 | * put JSON.parseObject(value) and not encode in public cases 15 | * @author Lemon 16 | * @see #put(String, Object) 17 | */ 18 | public class JSONRequest implements apijson.JSONRequest, ArrayList> { 19 | 20 | protected Map map = new LinkedHashMap<>(); 21 | public JSONRequest() { 22 | super(); 23 | } 24 | /** 25 | * encode = true 26 | * {@link #JSONRequest(String, Object)} 27 | * @param object 28 | */ 29 | public JSONRequest(Object object) { 30 | super(); 31 | put(object); 32 | } 33 | /** 34 | * @param name 35 | * @param object 36 | */ 37 | public JSONRequest(String name, Object object) { 38 | super(); 39 | put(name, object); 40 | } 41 | 42 | ///**create a parent JSONMap named KEY_ARRAY 43 | // * @param count 44 | // * @param page 45 | // * @return {@link #toArray(int, int)} 46 | // */ 47 | //public LinkedHashMap toArray(int count, int page) { 48 | // return toArray(count, page, null); 49 | //} 50 | // 51 | ///**create a parent JSONMap named name+KEY_ARRAY. 52 | // * @param count 53 | // * @param page 54 | // * @param name 55 | // * @return {name+KEY_ARRAY : this}. if needs to be put, use {@link #putsAll(Map)} instead 56 | // */ 57 | //public LinkedHashMap toArray(int count, int page, String name) { 58 | // return new JSONRequest(StringUtil.get(name) + KEY_ARRAY, this.setCount(count).setPage(page)); 59 | //} 60 | 61 | @Override 62 | public JSONRequest putsAll(Map m) { 63 | putAll(m); 64 | return this; 65 | } 66 | 67 | /** 68 | * @param value 69 | * @return {@link #puts(String, Object)} 70 | */ 71 | @Override 72 | public JSONRequest puts(Object value) { 73 | put(value); 74 | return this; 75 | } 76 | /** 77 | * @param key 78 | * @param value 79 | * @return this 80 | * @see {@link #put(String, Object)} 81 | */ 82 | @Override 83 | public JSONRequest puts(String key, Object value) { 84 | put(key, value); 85 | return this; 86 | } 87 | 88 | 89 | /**自定义类型必须转为JSONObject或JSONArray,否则RequestParser解析不了 90 | */ 91 | @Override 92 | public Object put(String key, Object value) { 93 | if (value == null) {// || key == null 94 | return null; 95 | } 96 | 97 | Object target = null; 98 | try { 99 | target = JSON.parse(value); 100 | } catch (Exception e) { 101 | // nothing 102 | e.printStackTrace(); 103 | } 104 | // if (target == null) { // "tag":"User" 报错 105 | // return null; 106 | // } 107 | return map.put(StringUtil.isNotEmpty(key, true) ? key : value.getClass().getSimpleName() //must handle key here 108 | , target == null ? value : target); 109 | } 110 | 111 | 112 | @Override 113 | public int size() { 114 | return map.size(); 115 | } 116 | 117 | @Override 118 | public boolean isEmpty() { 119 | return map.isEmpty(); 120 | } 121 | 122 | @Override 123 | public boolean containsKey(Object key) { 124 | return map.containsKey(key); 125 | } 126 | 127 | @Override 128 | public boolean containsValue(Object value) { 129 | return map.containsValue(value); 130 | } 131 | 132 | @Override 133 | public Object get(Object key) { 134 | return map.get(key); 135 | } 136 | 137 | @Override 138 | public Object remove(Object key) { 139 | return map.remove(key); 140 | } 141 | 142 | 143 | @Override 144 | public void clear() { 145 | map.clear(); 146 | } 147 | 148 | @Override 149 | public Set keySet() { 150 | return map.keySet(); 151 | } 152 | 153 | @Override 154 | public Collection values() { 155 | return map.values(); 156 | } 157 | 158 | @Override 159 | public Set> entrySet() { 160 | return map.entrySet(); 161 | } 162 | 163 | @Override 164 | public String toString() { 165 | return JSON.toJSONString(map); 166 | } 167 | 168 | public String toJSONString() { 169 | return JSON.toJSONString(map); 170 | } 171 | 172 | } 173 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/Join.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import apijson.NotNull; 12 | import apijson.StringUtil; 13 | 14 | /**连表 配置 15 | * @author Lemon 16 | */ 17 | public class Join, L extends List> { 18 | 19 | private String path; // /User/id@ 20 | 21 | private String joinType; // "@" - APP, "<" - LEFT, ">" - RIGHT, "*" - CROSS, "&" - INNER, "|" - FULL, "!" - OUTER, "^" - SIDE, "(" - ANTI, ")" - FOREIGN, "~" ASOF 22 | private String table; // User 23 | private String alias; // owner 24 | private int count = 1; // 当app join子表,需要返回子表的行数,默认1行; 25 | private List onList; // ON User.id = Moment.userId AND ... 26 | 27 | private M request; // { "id@":"/Moment/userId" } 28 | private M outer; // "join": { " joinConfig; 31 | private SQLConfig cacheConfig; 32 | private SQLConfig outerConfig; 33 | 34 | 35 | public String getPath() { 36 | return path; 37 | } 38 | public void setPath(String path) { 39 | this.path = path; 40 | } 41 | 42 | public int getCount() { 43 | return count; 44 | } 45 | public void setCount(int count) { 46 | this.count = count; 47 | } 48 | 49 | public String getJoinType() { 50 | return joinType; 51 | } 52 | public void setJoinType(String joinType) { 53 | this.joinType = joinType; 54 | } 55 | public String getTable() { 56 | return table; 57 | } 58 | public void setTable(String table) { 59 | this.table = table; 60 | } 61 | public String getAlias() { 62 | return alias; 63 | } 64 | public void setAlias(String alias) { 65 | this.alias = alias; 66 | } 67 | 68 | public List getOnList() { 69 | return onList; 70 | } 71 | public void setOnList(List onList) { 72 | this.onList = onList; 73 | } 74 | 75 | public M getRequest() { 76 | return request; 77 | } 78 | public void setRequest(M request) { 79 | this.request = request; 80 | } 81 | public M getOuter() { 82 | return outer; 83 | } 84 | public void setOuter(M outer) { 85 | this.outer = outer; 86 | } 87 | 88 | public SQLConfig getJoinConfig() { 89 | return joinConfig; 90 | } 91 | public void setJoinConfig(SQLConfig joinConfig) { 92 | this.joinConfig = joinConfig; 93 | } 94 | public SQLConfig getCacheConfig() { 95 | return cacheConfig; 96 | } 97 | public void setCacheConfig(SQLConfig cacheConfig) { 98 | this.cacheConfig = cacheConfig; 99 | } 100 | public SQLConfig getOuterConfig() { 101 | return outerConfig; 102 | } 103 | public void setOuterConfig(SQLConfig outerConfig) { 104 | this.outerConfig = outerConfig; 105 | } 106 | 107 | public boolean isOne2One() { 108 | return ! isOne2Many(); 109 | } 110 | public boolean isOne2Many() { 111 | return count != 1 || (path != null && path.contains("[]")); // TODO 必须保证一对一时不会传包含 [] 的 path 112 | } 113 | 114 | public boolean isAppJoin() { 115 | return "@".equals(getJoinType()); 116 | } 117 | public boolean isLeftJoin() { 118 | return "<".equals(getJoinType()); 119 | } 120 | public boolean isRightJoin() { 121 | return ">".equals(getJoinType()); 122 | } 123 | public boolean isCrossJoin() { 124 | return "*".equals(getJoinType()); 125 | } 126 | public boolean isInnerJoin() { 127 | return "&".equals(getJoinType()); 128 | } 129 | public boolean isFullJoin() { 130 | String jt = getJoinType(); 131 | return "".equals(jt) || "|".equals(jt); 132 | } 133 | public boolean isOuterJoin() { 134 | return "!".equals(getJoinType()); 135 | } 136 | public boolean isSideJoin() { 137 | return "^".equals(getJoinType()); 138 | } 139 | public boolean isAntiJoin() { 140 | return "(".equals(getJoinType()); 141 | } 142 | public boolean isForeignJoin() { 143 | return ")".equals(getJoinType()); 144 | } 145 | public boolean isAsofJoin() { 146 | return "~".equals(getJoinType()); 147 | } 148 | 149 | public boolean isLeftOrRightJoin() { 150 | String jt = getJoinType(); 151 | return "<".equals(jt) || ">".equals(jt); 152 | } 153 | 154 | public boolean canCacheViceTable() { 155 | String jt = getJoinType(); 156 | return "@".equals(jt) || "<".equals(jt) || ">".equals(jt) || "&".equals(jt) || "*".equals(jt) || ")".equals(jt); 157 | // 副表是按常规条件查询,缓存会导致其它同表同条件对象查询结果集为空 return ! isFullJoin(); // ! - OUTER, ( - FOREIGN 都需要缓存空副表数据,避免多余的查询 158 | } 159 | 160 | public boolean isSQLJoin() { 161 | return ! isAppJoin(); 162 | } 163 | 164 | public static boolean isSQLJoin(Join j) { 165 | return j != null && j.isSQLJoin(); 166 | } 167 | 168 | public static boolean isAppJoin(Join j) { 169 | return j != null && j.isAppJoin(); 170 | } 171 | 172 | public static boolean isLeftOrRightJoin(Join j) { 173 | return j != null && j.isLeftOrRightJoin(); 174 | } 175 | 176 | 177 | 178 | public static class On { 179 | 180 | private String originKey; 181 | private String originValue; 182 | 183 | private Logic logic; // & | ! 184 | private String relateType; // "" - 一对一, "{}" - 一对多, "<>" - 多对一, > , <= , != 185 | private String key; // id 186 | private String targetTableKey; // Moment:main 187 | private String targetTable; // Moment 188 | private String targetAlias; // main 189 | private String targetKey; // userId 190 | 191 | public String getOriginKey() { 192 | return originKey; 193 | } 194 | public void setOriginKey(String originKey) { 195 | this.originKey = originKey; 196 | } 197 | public String getOriginValue() { 198 | return originValue; 199 | } 200 | public void setOriginValue(String originValue) { 201 | this.originValue = originValue; 202 | } 203 | 204 | 205 | public Logic getLogic() { 206 | return logic; 207 | } 208 | public void setLogic(Logic logic) { 209 | this.logic = logic; 210 | } 211 | public String getRelateType() { 212 | return relateType; 213 | } 214 | public void setRelateType(String relateType) { 215 | this.relateType = relateType; 216 | } 217 | 218 | public String getKey() { 219 | return key; 220 | } 221 | public void setKey(String key) { 222 | this.key = key; 223 | } 224 | 225 | public void setTargetTableKey(String targetTableKey) { 226 | this.targetTableKey = targetTableKey; 227 | } 228 | public String getTargetTableKey() { 229 | return targetTableKey; 230 | } 231 | 232 | public void setTargetTable(String targetTable) { 233 | this.targetTable = targetTable; 234 | } 235 | public String getTargetTable() { 236 | return targetTable; 237 | } 238 | public void setTargetAlias(String targetAlias) { 239 | this.targetAlias = targetAlias; 240 | } 241 | public String getTargetAlias() { 242 | return targetAlias; 243 | } 244 | public String getTargetKey() { 245 | return targetKey; 246 | } 247 | public void setTargetKey(String targetKey) { 248 | this.targetKey = targetKey; 249 | } 250 | 251 | 252 | public void setKeyAndType(String joinType, String table, @NotNull String originKey) throws Exception { //id, id@, id{}@, contactIdList<>@ ... 253 | if (originKey.endsWith("@")) { 254 | originKey = originKey.substring(0, originKey.length() - 1); 255 | } 256 | else { //TODO 暂时只允许 User.id = Moment.userId 字段关联,不允许 User.id = 82001 这种 257 | throw new IllegalArgumentException(joinType + "/.../" + table + "/" + originKey + " 中字符 " + originKey + " 不合法!join:'.../refKey'" + " 中 refKey 必须以 @ 结尾!"); 258 | } 259 | 260 | String k; 261 | 262 | if (originKey.endsWith("{}")) { 263 | setRelateType("{}"); 264 | k = originKey.substring(0, originKey.length() - 2); 265 | } 266 | else if (originKey.endsWith("<>")) { 267 | setRelateType("<>"); 268 | k = originKey.substring(0, originKey.length() - 2); 269 | } 270 | else if (originKey.endsWith("$")) { // key%$:"a" -> key LIKE '%a%'; key?%$:"a" -> key LIKE 'a%'; key_?$:"a" -> key LIKE '_a'; key_%$:"a" -> key LIKE '_a%' 271 | k = originKey.substring(0, originKey.length() - 1); 272 | char c = k.isEmpty() ? 0 : k.charAt(k.length() - 1); 273 | 274 | String t = "$"; 275 | if (c == '%' || c == '_' || c == '?') { 276 | t = c + t; 277 | k = k.substring(0, k.length() - 1); 278 | 279 | char c2 = k.isEmpty() ? 0 : k.charAt(k.length() - 1); 280 | if (c2 == '%' || c2 == '_' || c2 == '?') { 281 | if (c2 == c) { 282 | throw new IllegalArgumentException(originKey + ":value 中字符 " + k + " 不合法!key$:value 中不允许 key 中有连续相同的占位符!"); 283 | } 284 | 285 | t = c2 + t; 286 | k = k.substring(0, k.length() - 1); 287 | } 288 | else if (c == '?') { 289 | throw new IllegalArgumentException(originKey + ":value 中字符 " + originKey + " 不合法!key$:value 中不允许只有单独的 '?',必须和 '%', '_' 之一配合使用 !"); 290 | } 291 | } 292 | 293 | setRelateType(t); 294 | } 295 | else if (originKey.endsWith("~")) { 296 | boolean ignoreCase = originKey.endsWith("*~"); 297 | setRelateType(ignoreCase ? "*~" : "~"); 298 | k = originKey.substring(0, originKey.length() - (ignoreCase ? 2 : 1)); 299 | } 300 | else if (originKey.endsWith(">=")) { 301 | setRelateType(">="); 302 | k = originKey.substring(0, originKey.length() - 2); 303 | } 304 | else if (originKey.endsWith("<=")) { 305 | setRelateType("<="); 306 | k = originKey.substring(0, originKey.length() - 2); 307 | } 308 | else if (originKey.endsWith(">")) { 309 | setRelateType(">"); 310 | k = originKey.substring(0, originKey.length() - 1); 311 | } 312 | else if (originKey.endsWith("<")) { 313 | setRelateType("<"); 314 | k = originKey.substring(0, originKey.length() - 1); 315 | } 316 | else { 317 | setRelateType(""); 318 | k = originKey; 319 | } 320 | 321 | if (k != null && (k.contains("&") || k.contains("|"))) { 322 | throw new UnsupportedOperationException(joinType + "/.../" + table + "/" + originKey + " 中字符 " + k + " 不合法!与或非逻辑符仅支持 '!' 非逻辑符 !"); 323 | } 324 | 325 | //TODO if (c3 == '-') { // 表示 key 和 value 顺序反过来: value LIKE key 326 | 327 | Logic l = new Logic(k); 328 | setLogic(l); 329 | 330 | if (StringUtil.isName(l.getKey()) == false) { 331 | throw new IllegalArgumentException(joinType + "/.../" + table + "/" + originKey + " 中字符 " + l.getKey() + " 不合法!必须符合字段命名格式!"); 332 | } 333 | 334 | setKey(l.getKey()); 335 | } 336 | 337 | } 338 | 339 | } 340 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/Logic.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import apijson.StringUtil; 9 | 10 | /**& | !逻辑 11 | * @author Lemon 12 | */ 13 | public class Logic { 14 | 15 | public static final int TYPE_OR = 0; 16 | public static final int TYPE_AND = 1; 17 | public static final int TYPE_NOT = 2; 18 | public static final int[] TYPES = {TYPE_OR, TYPE_AND, TYPE_NOT}; 19 | 20 | public static final String CHAR_OR = "|"; 21 | public static final String CHAR_AND = "&"; 22 | public static final String CHAR_NOT = "!"; 23 | public static final String[] CHARS = {CHAR_OR, CHAR_AND, CHAR_NOT}; 24 | 25 | public static final String NAME_OR = "OR"; 26 | public static final String NAME_AND = "AND"; 27 | public static final String NAME_NOT = "NOT"; 28 | public static final String[] NAMES = {NAME_OR, NAME_AND, NAME_NOT}; 29 | 30 | 31 | private int type; 32 | private String key; 33 | private String originKey; 34 | 35 | public Logic() { 36 | super(); 37 | } 38 | 39 | public Logic(int type) { 40 | this(); 41 | this.type = type; 42 | } 43 | public Logic(String key) { 44 | this.originKey = key; 45 | key = StringUtil.get(key); 46 | 47 | int type = getType(key.isEmpty() ? "" : key.substring(key.length() - 1)); 48 | 49 | if (type >= 0 && type <= 2) { 50 | key = key.substring(0, key.length() - 1); 51 | } 52 | if (type < 0) { 53 | type = 0; 54 | } 55 | 56 | 57 | setType(type); 58 | setKey(key); 59 | } 60 | 61 | 62 | public int getType() { 63 | return type; 64 | } 65 | 66 | public void setType(int type) { 67 | this.type = type; 68 | } 69 | 70 | public String getKey() { 71 | return key; 72 | } 73 | public void setKey(String key) { 74 | this.key = key; 75 | } 76 | public String getOriginKey() { 77 | return originKey; 78 | } 79 | 80 | 81 | public boolean isOr() { 82 | return isOr(type); 83 | } 84 | public static boolean isOr(int type) { 85 | return type == TYPE_OR; 86 | } 87 | public boolean isAnd() { 88 | return isAnd(type); 89 | } 90 | public static boolean isAnd(int type) { 91 | return type == TYPE_AND; 92 | } 93 | public boolean isNot() { 94 | return isNot(type); 95 | } 96 | public static boolean isNot(int type) { 97 | return type == TYPE_NOT; 98 | } 99 | 100 | public boolean isCorrect() { 101 | return isContain(getType()); 102 | } 103 | public static boolean isContain(String s) { 104 | return isContain(getType(s)); 105 | } 106 | public static boolean isContain(int type) { 107 | return type >= TYPE_OR && type <= TYPE_NOT; 108 | } 109 | 110 | public static int getType(char logicChar) { 111 | return getType(String.valueOf(logicChar)); 112 | } 113 | public static int getType(String logicChar) { 114 | int type = -1; 115 | if (logicChar != null && logicChar.length() == 1) { 116 | switch (logicChar) { 117 | case "|": 118 | type = 0; 119 | break; 120 | case "&": 121 | type = 1; 122 | break; 123 | case "!": 124 | type = 2; 125 | break; 126 | } 127 | } 128 | return type; 129 | } 130 | 131 | public String getChar() { 132 | return getChar(type); 133 | } 134 | public static String getChar(int type) { 135 | return type < 0 || type >= CHARS.length ? "" : CHARS[type]; 136 | } 137 | 138 | public String getName() { 139 | return getName(type); 140 | } 141 | public static String getName(int type) { 142 | return type < 0 || type >= NAMES.length ? "" : NAMES[type]; 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/ObjectParser.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import apijson.*; 12 | 13 | /**简化Parser,getObject和getArray(getArrayConfig)都能用 14 | * @author Lemon 15 | */ 16 | public interface ObjectParser, L extends List> { 17 | 18 | Parser getParser(); 19 | ObjectParser setParser(Parser parser); 20 | 21 | String getParentPath(); 22 | ObjectParser setParentPath(String parentPath); 23 | 24 | ObjectParser setCache(M cache); 25 | M getCache(); 26 | 27 | 28 | /**解析成员 29 | * response重新赋值 30 | * @param name 31 | * @param isReuse 32 | * @return null or this 33 | * @throws Exception 34 | */ 35 | ObjectParser parse(String name, boolean isReuse) throws Exception; 36 | 37 | /**调用 parser 的 sqlExecutor 来解析结果 38 | * @param method 39 | * @param table 40 | * @param alias 41 | * @param request 42 | * @param joinList 43 | * @param isProcedure 44 | * @return 45 | * @throws Exception 46 | */ 47 | M parseResponse(RequestMethod method, String table, String alias, M request, List> joinList, boolean isProcedure) throws Exception; 48 | /**调用 parser 的 sqlExecutor 来解析结果 49 | * @param config 50 | * @param isProcedure 51 | * @return 52 | * @throws Exception 53 | */ 54 | M parseResponse(SQLConfig config, boolean isProcedure) throws Exception; 55 | 56 | 57 | 58 | /**解析普通成员 59 | * @param key 60 | * @param value 61 | * @return whether parse succeed 62 | */ 63 | boolean onParse(@NotNull String key, @NotNull Object value) throws Exception; 64 | 65 | /**解析子对象 66 | * @param index 67 | * @param key 68 | * @param value 69 | * @param cache SQL 结果缓存 70 | * @return 71 | * @throws Exception 72 | */ 73 | Object onChildParse(int index, String key, M value, Object cache) throws Exception; 74 | 75 | /**解析赋值引用 76 | * @param path 77 | * @return 78 | */ 79 | Object onReferenceParse(@NotNull String path); 80 | 81 | //TODO 改用 MySQL json_add,json_remove,json_contains 等函数! 82 | /**修改数组 PUT key:[] 83 | * @param key 84 | * @param array 85 | * @throws Exception 86 | */ 87 | void onPUTArrayParse(@NotNull String key, @NotNull L array) throws Exception; 88 | 89 | /**批量新增或修改 POST or PUT Table[]:[{}] 90 | * @param key 91 | * @param array 92 | * @throws Exception 93 | */ 94 | void onTableArrayParse(@NotNull String key, @NotNull L array) throws Exception; 95 | 96 | /**SQL 配置,for single object 97 | * @return {@link #setSQLConfig(int, int, int)} 98 | * @throws Exception 99 | */ 100 | ObjectParser setSQLConfig() throws Exception; 101 | 102 | /**SQL 配置 103 | * @return 104 | * @throws Exception 105 | */ 106 | ObjectParser setSQLConfig(int count, int page, int position) throws Exception; 107 | 108 | 109 | /**执行 SQL 110 | * @return 111 | * @throws Exception 112 | */ 113 | ObjectParser executeSQL() throws Exception; 114 | 115 | 116 | /** 117 | * @return 118 | * @throws Exception 119 | */ 120 | M onSQLExecute() throws Exception; 121 | 122 | 123 | /** 124 | * @return response 125 | * @throws Exception 126 | */ 127 | M response() throws Exception; 128 | 129 | void onFunctionResponse(String type) throws Exception; 130 | 131 | void onChildResponse() throws Exception; 132 | 133 | 134 | SQLConfig newSQLConfig(boolean isProcedure) throws Exception; 135 | SQLConfig newSQLConfig(RequestMethod method, String table, String alias, M request, List> joinList, boolean isProcedure) throws Exception; 136 | 137 | /** 138 | * response has the final value after parse (and query if isTableKey) 139 | */ 140 | void onComplete(); 141 | 142 | 143 | /**回收内存 144 | */ 145 | void recycle(); 146 | 147 | 148 | ObjectParser setMethod(RequestMethod method); 149 | RequestMethod getMethod(); 150 | 151 | 152 | boolean isTable(); 153 | String getPath(); 154 | String getTable(); 155 | String getAlias(); 156 | SQLConfig getArrayConfig(); 157 | 158 | SQLConfig getSQLConfig(); 159 | M getResponse(); 160 | M getSQLRequest(); 161 | M getSQLResponse(); 162 | 163 | Map getCustomMap(); 164 | Map> getFunctionMap(); 165 | Map getChildMap(); 166 | 167 | } 168 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/OnParseCallback.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author Lemon 13 | */ 14 | public abstract class OnParseCallback, L extends List> { 15 | 16 | 17 | /** 18 | * @param key 19 | * @param to 20 | * @param ro 21 | * @return false ? continue 22 | * @throws Exception 23 | */ 24 | protected boolean onParse(String key, Object to, Object ro) throws Exception { 25 | return true; 26 | } 27 | 28 | /** 29 | * @param key 30 | * @param to 31 | * @param ro 32 | * @return 33 | * @throws Exception 34 | */ 35 | protected Object onParseObject(String key, Object to, Object ro) throws Exception { 36 | return ro; 37 | } 38 | 39 | /** 40 | * @param key 41 | * @param tobj 42 | * @param robj 43 | * @return 44 | * @throws Exception 45 | */ 46 | protected M onParseJSONObject(String key, M tobj, M robj) throws Exception { 47 | return robj; 48 | } 49 | 50 | /** 51 | * @param key 52 | * @param tarray 53 | * @param rarray 54 | * @return 55 | * @throws Exception 56 | */ 57 | protected L onParseJSONArray(String key, L tarray, L rarray) throws Exception { 58 | return rarray; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/Operation.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | /**对请求 JSON 的操作 9 | * @author Lemon 10 | */ 11 | public enum Operation { 12 | /** 13 | * 必须传的字段,结构是 14 | * "key0,key1,key2..." 15 | */ 16 | MUST, 17 | 18 | /** 19 | * 不允许传的字段,结构是 20 | * "key0,key1,key2..." 21 | */ 22 | REFUSE, 23 | 24 | /**TODO 是否应该把数组类型写成 BOOLEANS, NUMBERS 等复数单词,以便抽取 enum ?扩展用 VERIFY 或 INSERT/UPDATE 远程函数等 25 | * 验证是否符合预设的类型: 26 | * BOOLEAN, NUMBER, DECIMAL, STRING, URL, DATE, TIME, DATETIME, OBJECT, ARRAY 27 | * 或它们的数组 28 | * BOOLEAN[], NUMBER[], DECIMAL[], STRING[], URL[], DATE[], TIME[], DATETIME[], OBJECT[], ARRAY[] 29 | * 结构是 30 | * { 31 | * key0: value0, 32 | * key1: value1, 33 | * key2: value2 34 | * ... 35 | * } 36 | * 例如 37 | * { 38 | * "id": "NUMBER", //id 类型必须为 NUMBER 39 | * "pictureList": "URL[]", //pictureList 类型必须为 URL[] 40 | * } 41 | * @see {@link AbstractVerifier#verifyType(String, String, Object, boolean)} 42 | */ 43 | TYPE, 44 | 45 | /** 46 | * 验证是否符合预设的条件,结构是 47 | * { 48 | * key0: value0, 49 | * key1: value1, 50 | * key2: value2 51 | * ... 52 | * } 53 | * 例如 54 | * { 55 | * "phone~": "PHONE", //phone 必须满足 PHONE 的格式,配置见 {@link AbstractVerifier#COMPILE_MAP} 56 | * "status{}": [1,2,3], //status 必须在给出的范围内 57 | * "content{L}": ">0,<=255", //content的长度 必须在给出的范围内 58 | * "balance&{}":">0,<=10000" //必须满足 balance>0 & balance<=10000 59 | * } 60 | */ 61 | VERIFY, 62 | 63 | /** 64 | * 验证是否存在,结构是 65 | * "key0,key1,key2..." 66 | * 多个字段用逗号隔开,联合校验 67 | */ 68 | EXIST, 69 | 70 | /** 71 | * 验证是否不存在,除了本身的记录,结构是 72 | * "key0,key1,key2..." 73 | * 多个字段用逗号隔开,联合校验 74 | */ 75 | UNIQUE, 76 | 77 | 78 | /** 79 | * 添加,当要被添加的对象不存在时,结构是 80 | * { 81 | * key0: value0, 82 | * key1: value1, 83 | * key2: value2 84 | * ... 85 | * } 86 | */ 87 | INSERT, 88 | 89 | /** 90 | * 强行放入,不存在时就添加,存在时就修改,结构是 91 | * { 92 | * key0: value0, 93 | * key1: value1, 94 | * key2: value2 95 | * ... 96 | * } 97 | */ 98 | UPDATE, 99 | 100 | /** 101 | * 替换,当要被替换的对象存在时,结构是 102 | * { 103 | * key0: value0, 104 | * key1: value1, 105 | * key2: value2 106 | * ... 107 | * } 108 | */ 109 | REPLACE, 110 | 111 | /** 112 | * 移除,当要被移除的对象存在时,结构是 113 | * "key0,key1,key2..." 114 | */ 115 | REMOVE, 116 | 117 | /** 118 | * 监听事件,用于同步到其它表,结构是 119 | * "key0": {} 120 | * 例如 "name": { "UPDATE": { "Comment": { "userName@": "/name" } } } 121 | * 当 User.name 被修改时,同步修改 Comment.userName 122 | * 123 | * 例如 "sex != 0 && sex != 1": "throw new Error('sex 必须在 [0, 1] 内!')" 124 | * 自定义代码,当满足条件是执行后面的代码 125 | * 126 | * 还有 127 | * "ELSE": "" 128 | * 自定义代码,不处理,和不传一样 129 | */ 130 | IF, 131 | 132 | // /** 直接用 IF 替代 133 | // * 自定义代码,结构是 "code",例如 134 | // * "var a = 1; 135 | // * var b = a + 2; 136 | // * if (b % 2 == 0) { 137 | // * throw new Error('b % 2 == 0 !'); 138 | // * } 139 | // * " 140 | // * 141 | // * 或 { "code": "JS", "code2": "LUA" } 142 | // */ 143 | // CODE, 144 | 145 | /** 146 | * 允许批量增删改部分失败,结构是 147 | * "Table[],key[],key:alias[]" 148 | * 自动 ALLOW_PARTIAL_UPDATE_FAILED_TABLE_MAP.put,结构是 Boolean,例如 true 149 | */ 150 | ALLOW_PARTIAL_UPDATE_FAIL, 151 | 152 | /** 153 | * 强制要求必须有 id/id{}/id{}@ 条件,结构是 Boolean,例如 true 154 | */ 155 | IS_ID_CONDITION_MUST; 156 | 157 | } 158 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/Pair.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.util.Collection; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | import apijson.StringUtil; 13 | 14 | /**key:value 15 | * @author Lemon 16 | */ 17 | public class Pair extends Entry { 18 | 19 | private static final Map> CLASS_MAP; 20 | static { 21 | CLASS_MAP = new HashMap>(); 22 | CLASS_MAP.put(boolean.class.getSimpleName(), boolean.class); 23 | CLASS_MAP.put(int.class.getSimpleName(), int.class); 24 | CLASS_MAP.put(long.class.getSimpleName(), long.class); 25 | CLASS_MAP.put(float.class.getSimpleName(), float.class); 26 | CLASS_MAP.put(double.class.getSimpleName(), double.class); 27 | CLASS_MAP.put(Boolean.class.getSimpleName(), Boolean.class); 28 | CLASS_MAP.put(Integer.class.getSimpleName(), Integer.class); 29 | CLASS_MAP.put(Long.class.getSimpleName(), Long.class); 30 | CLASS_MAP.put(Float.class.getSimpleName(), Float.class); 31 | CLASS_MAP.put(Double.class.getSimpleName(), Double.class); 32 | 33 | CLASS_MAP.put(Object.class.getSimpleName(), Object.class); 34 | CLASS_MAP.put(String.class.getSimpleName(), String.class); 35 | CLASS_MAP.put(Collection.class.getSimpleName(), Collection.class);//不允许指定 36 | CLASS_MAP.put(Map.class.getSimpleName(), Map.class);//不允许指定 37 | // CLASS_MAP.put(JSONMap.class.getSimpleName(), JSONMap.class);//必须有,Map中没有getLongValue等方法 38 | // CLASS_MAP.put(JSONList.class.getSimpleName(), JSONList.class);//必须有,Collection中没有getJSONObject等方法 39 | } 40 | 41 | 42 | public Pair() { 43 | super(); 44 | } 45 | 46 | public boolean isEmpty(boolean trim) { 47 | return StringUtil.isNotEmpty(key, trim) == false && StringUtil.isNotEmpty(value, trim) == false; 48 | } 49 | 50 | /** 51 | * @param 52 | * @param pair 53 | * @return 54 | */ 55 | public static boolean isCorrect(Entry pair) { 56 | return pair != null && StringUtil.isNotEmpty(pair.getValue(), true); 57 | } 58 | 59 | /** 60 | * @return 61 | */ 62 | public String toPairString() { 63 | return toPairString(getKey(), getValue()); 64 | } 65 | /** 66 | * @param typeKey 67 | * @param valueKey 68 | * @return 69 | */ 70 | public static String toPairString(String typeKey, String valueKey) { 71 | return (typeKey == null ? "" : typeKey + ":") + valueKey; 72 | } 73 | /** 74 | * @param type 75 | * @param value 76 | * @return 77 | */ 78 | public static String toPairString(Class type, Object value) { 79 | return toPairString(type == null ? null : type.getSimpleName(), StringUtil.get(value)); 80 | } 81 | 82 | /** 83 | * isRightValueDefault = false; 84 | * "key":null不应该出现?因为FastJSON内默认不存null 85 | * @param pair leftKey:rightValue 86 | * @return {@link #parseEntry(String, boolean)} 87 | */ 88 | public static Entry parseEntry(String pair) { 89 | return parseEntry(pair, false); 90 | } 91 | /** 92 | * isRightValueDefault = false; 93 | * "key":null不应该出现?因为FastJSON内默认不存null 94 | * @param pair leftKey:rightValue 95 | * @param isRightValueDefault 右边值缺省,当pair不包含 : 时默认整个pair为leftKey;false-相反 96 | * @return {@link #parseEntry(String, boolean, String)} 97 | */ 98 | public static Entry parseEntry(String pair, boolean isRightValueDefault) { 99 | return parseEntry(pair, isRightValueDefault, null); 100 | } 101 | /** 102 | * "key":null不应该出现?因为FastJSON内默认不存null 103 | * @param pair leftKey:rightValue 104 | * @param isRightValueDefault 右边值缺省,当pair不包含 : 时默认整个pair为leftKey;false-相反 105 | * @param defaultValue 缺省值 106 | * @return @NonNull 107 | */ 108 | public static Entry parseEntry(String pair, boolean isRightValueDefault, String defaultValue) { 109 | pair = StringUtil.get(pair);//让客户端去掉所有空格 getNoBlankString(pair); 110 | Entry entry = new Entry(); 111 | if (pair.isEmpty() == false) { 112 | int index = pair.indexOf(":"); 113 | if (index < 0) { 114 | entry.setKey(isRightValueDefault ? pair : defaultValue); 115 | entry.setValue(isRightValueDefault ? defaultValue : pair); 116 | } else { 117 | entry.setKey(pair.substring(0, index)); 118 | entry.setValue(pair.substring(index + 1, pair.length())); 119 | } 120 | 121 | } 122 | return entry; 123 | } 124 | /** 125 | * @param pair 126 | * @return 127 | */ 128 | public static Entry parseVariableEntry(String pair) { 129 | return parseEntry(pair, false, Object.class.getSimpleName()); 130 | } 131 | /** 132 | * @param pair 133 | * @param valueMap 134 | * @return 135 | */ 136 | public static Entry, Object> parseVariableEntry(String pair, Map valueMap) { 137 | pair = StringUtil.get(pair);//让客户端去掉所有空格 getNoBlankString(pair); 138 | Entry, Object> entry = new Entry, Object>(); 139 | if (pair.isEmpty() == false) { 140 | int index = pair.contains(":") ? pair.indexOf(":") : -1; 141 | 142 | entry.setKey(CLASS_MAP.get(index < 0 ? Object.class.getSimpleName() : pair.substring(0, index))); 143 | entry.setValue(valueMap == null ? null : valueMap.get(pair.substring(index + 1, pair.length()))); 144 | } 145 | return entry; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/Parser.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.sql.SQLException; 9 | import java.sql.Savepoint; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | import apijson.*; 14 | 15 | /**解析器 16 | * @author Lemon 17 | */ 18 | public interface Parser, L extends List> 19 | extends ParserCreator, VerifierCreator, SQLCreator { 20 | 21 | @NotNull 22 | Visitor getVisitor(); 23 | Parser setVisitor(@NotNull Visitor visitor); 24 | 25 | @NotNull 26 | RequestMethod getMethod(); 27 | Parser setMethod(@NotNull RequestMethod method); 28 | 29 | int getVersion(); 30 | Parser setVersion(int version); 31 | 32 | String getTag(); 33 | Parser setTag(String tag); 34 | 35 | M getRequest(); 36 | Parser setRequest(M request); 37 | 38 | Parser setNeedVerify(boolean needVerify); 39 | 40 | boolean isNeedVerifyLogin(); 41 | Parser setNeedVerifyLogin(boolean needVerifyLogin); 42 | 43 | boolean isNeedVerifyRole(); 44 | Parser setNeedVerifyRole(boolean needVerifyRole); 45 | 46 | boolean isNeedVerifyContent(); 47 | Parser setNeedVerifyContent(boolean needVerifyContent); 48 | 49 | 50 | String parse(String request); 51 | String parse(M request); 52 | 53 | M parseResponse(String request); 54 | M parseResponse(M request); 55 | 56 | // 没必要性能还差 JSONRequest parseCorrectResponse(String table, JSONRequest response) throws Exception; 57 | 58 | 59 | M parseCorrectRequest() throws Exception; 60 | 61 | M parseCorrectRequest(RequestMethod method, String tag, int version, String name, M request, 62 | int maxUpdateCount, SQLCreator creator) throws Exception; 63 | 64 | 65 | Map getStructure(String table, String method, String tag, int version) throws Exception; 66 | 67 | 68 | M onObjectParse(M request, String parentPath, String name, SQLConfig arrayConfig, boolean isSubquery, M cache) throws Exception; 69 | 70 | L onArrayParse(M request, String parentPath, String name, boolean isSubquery, L cache) throws Exception; 71 | 72 | /**解析远程函数 73 | * @param key 74 | * @param function 75 | * @param parentPath 76 | * @param currentName 77 | * @param currentObject 78 | * @return 79 | * @throws Exception 80 | */ 81 | Object onFunctionParse(String key, String function, String parentPath, String currentName, M currentObject, boolean containRaw) throws Exception; 82 | 83 | ObjectParser createObjectParser(M request, String parentPath, SQLConfig arrayConfig, boolean isSubquery, boolean isTable, boolean isArrayMainTable) throws Exception; 84 | 85 | int getMinQueryPage(); 86 | int getMaxQueryPage(); 87 | int getDefaultQueryCount(); 88 | int getMaxQueryCount(); 89 | int getMaxUpdateCount(); 90 | int getMaxSQLCount(); 91 | int getMaxObjectCount(); 92 | int getMaxArrayCount(); 93 | int getMaxQueryDepth(); 94 | 95 | void putQueryResult(String path, Object result); 96 | 97 | 98 | Object getValueByPath(String valuePath); 99 | 100 | 101 | void onVerifyLogin() throws Exception; 102 | void onVerifyContent() throws Exception; 103 | void onVerifyRole(SQLConfig config) throws Exception; 104 | 105 | M executeSQL(SQLConfig config, boolean isSubquery) throws Exception; 106 | 107 | SQLExecutor getSQLExecutor(); 108 | Verifier getVerifier(); 109 | 110 | 111 | Boolean getGlobalFormat(); 112 | String getGlobalRole(); 113 | String getGlobalDatabase(); 114 | String getGlobalDatasource(); 115 | String getGlobalNamespace(); 116 | String getGlobalCatalog(); 117 | String getGlobalSchema(); 118 | Boolean getGlobalExplain(); 119 | String getGlobalCache(); 120 | 121 | 122 | int getTransactionIsolation(); 123 | void setTransactionIsolation(int transactionIsolation); 124 | 125 | void begin(int transactionIsolation); 126 | void rollback() throws SQLException; 127 | void rollback(Savepoint savepoint) throws SQLException; 128 | void commit() throws SQLException; 129 | void close(); 130 | 131 | M newSuccessResult(); 132 | M newErrorResult(Exception e); 133 | 134 | } 135 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/ParserCreator.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import apijson.NotNull; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | /**SQL相关创建器 14 | * @author Lemon 15 | */ 16 | public interface ParserCreator, L extends List> { 17 | 18 | @NotNull 19 | Parser createParser(); 20 | 21 | @NotNull 22 | FunctionParser createFunctionParser(); 23 | } 24 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/SQLConfig.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import apijson.NotNull; 12 | import apijson.RequestMethod; 13 | import apijson.StringUtil; 14 | 15 | /**SQL配置 16 | * @author Lemon 17 | */ 18 | public interface SQLConfig, L extends List> { 19 | 20 | String DATABASE_MYSQL = "MYSQL"; // https://www.mysql.com 21 | String DATABASE_POSTGRESQL = "POSTGRESQL"; // https://www.postgresql.org 22 | String DATABASE_SQLSERVER = "SQLSERVER"; // https://www.microsoft.com/en-us/sql-server 23 | String DATABASE_ORACLE = "ORACLE"; // https://www.oracle.com/database 24 | String DATABASE_DB2 = "DB2"; // https://www.ibm.com/products/db2 25 | String DATABASE_MARIADB = "MARIADB"; // https://mariadb.org 26 | String DATABASE_TIDB = "TIDB"; // https://www.pingcap.com/tidb 27 | String DATABASE_COCKROACHDB = "COCKROACHDB"; // https://www.cockroachlabs.com 28 | String DATABASE_DAMENG = "DAMENG"; // https://www.dameng.com 29 | String DATABASE_KINGBASE = "KINGBASE"; // https://www.kingbase.com.cn 30 | String DATABASE_ELASTICSEARCH = "ELASTICSEARCH"; // https://www.elastic.co/guide/en/elasticsearch/reference/7.4/xpack-sql.html 31 | String DATABASE_MANTICORE = "MANTICORE"; // https://manticoresearch.com 32 | String DATABASE_CLICKHOUSE = "CLICKHOUSE"; // https://clickhouse.com 33 | String DATABASE_HIVE = "HIVE"; // https://hive.apache.org 34 | String DATABASE_PRESTO = "PRESTO"; // Facebook PrestoDB https://prestodb.io 35 | String DATABASE_TRINO = "TRINO"; // PrestoSQL https://trino.io 36 | String DATABASE_DORIS = "DORIS"; // https://doris.apache.org 37 | String DATABASE_SNOWFLAKE = "SNOWFLAKE"; // https://www.snowflake.com 38 | String DATABASE_DATABRICKS = "DATABRICKS"; // https://www.databricks.com 39 | String DATABASE_CASSANDRA = "CASSANDRA"; // https://cassandra.apache.org 40 | String DATABASE_MILVUS = "MILVUS"; // https://milvus.io 41 | String DATABASE_INFLUXDB = "INFLUXDB"; // https://www.influxdata.com/products/influxdb-overview 42 | String DATABASE_TDENGINE = "TDENGINE"; // https://tdengine.com 43 | String DATABASE_TIMESCALEDB = "TIMESCALEDB"; // https://www.timescale.com 44 | String DATABASE_QUESTDB = "QUESTDB"; // https://questdb.com 45 | String DATABASE_IOTDB = "IOTDB"; // https://iotdb.apache.org/zh/UserGuide/latest/API/Programming-JDBC.html 46 | 47 | String DATABASE_REDIS = "REDIS"; // https://redisql.com 48 | String DATABASE_MONGODB = "MONGODB"; // https://www.mongodb.com/docs/atlas/data-federation/query/query-with-sql 49 | String DATABASE_KAFKA = "KAFKA"; // https://github.com/APIJSON/APIJSON-Demo/tree/master/APIJSON-Java-Server/APIJSONDemo-MultiDataSource-Kafka 50 | String DATABASE_SQLITE = "SQLITE"; // https://www.sqlite.org 51 | String DATABASE_DUCKDB = "DUCKDB"; // https://duckdb.org 52 | String DATABASE_SURREALDB = "SURREALDB"; // https://surrealdb.com 53 | String DATABASE_OPENGAUSS = "OPENGAUSS"; // https://opengauss.org 54 | 55 | String DATABASE_MQ = "MQ"; // 56 | 57 | String SCHEMA_INFORMATION = "information_schema"; //MySQL, PostgreSQL, SQL Server 都有的系统模式 58 | String SCHEMA_SYS = "sys"; //SQL Server 系统模式 59 | String TABLE_SCHEMA = "table_schema"; 60 | String TABLE_NAME = "table_name"; 61 | 62 | int TYPE_CHILD = 0; 63 | int TYPE_ITEM = 1; 64 | int TYPE_ITEM_CHILD_0 = 2; 65 | 66 | Parser gainParser(); 67 | 68 | SQLConfig setParser(Parser parser); 69 | 70 | ObjectParser gainObjectParser(); 71 | 72 | SQLConfig setObjectParser(ObjectParser objectParser); 73 | 74 | int getVersion(); 75 | 76 | SQLConfig setVersion(int version); 77 | 78 | String getTag(); 79 | 80 | SQLConfig setTag(String tag); 81 | 82 | boolean isTSQL(); 83 | boolean isMSQL(); 84 | boolean isPSQL(); 85 | 86 | boolean isMySQL(); 87 | boolean isPostgreSQL(); 88 | boolean isSQLServer(); 89 | boolean isOracle(); 90 | boolean isDb2(); 91 | boolean isMariaDB(); 92 | boolean isTiDB(); 93 | boolean isCockroachDB(); 94 | boolean isDameng(); 95 | boolean isKingBase(); 96 | boolean isElasticsearch(); 97 | boolean isManticore(); 98 | boolean isClickHouse(); 99 | boolean isHive(); 100 | boolean isPresto(); 101 | boolean isTrino(); 102 | boolean isSnowflake(); 103 | boolean isDatabricks(); 104 | boolean isCassandra(); 105 | boolean isMilvus(); 106 | boolean isInfluxDB(); 107 | boolean isTDengine(); 108 | boolean isTimescaleDB(); 109 | boolean isQuestDB(); 110 | boolean isIoTDB(); 111 | boolean isRedis(); 112 | boolean isMongoDB(); 113 | boolean isKafka(); 114 | boolean isMQ(); 115 | boolean isSQLite(); 116 | boolean isDuckDB(); 117 | boolean isSurrealDB(); 118 | boolean isOpenGauss(); 119 | boolean isDoris(); 120 | 121 | 122 | // 暂时只兼容以上几种 123 | // boolean isSQL(); 124 | // boolean isTSQL(); 125 | // boolean isPLSQL(); 126 | // boolean isAnsiSQL(); 127 | 128 | /**用来给 Table, Column 等系统属性表来绕过 MAX_SQL_COUNT 等限制 129 | * @return 130 | */ 131 | boolean limitSQLCount(); 132 | 133 | /**是否开启 WITH AS 表达式来简化 SQL 和提升性能 134 | * @return 135 | */ 136 | boolean isWithAsEnable(); 137 | /**允许增删改部分失败 138 | * @return 139 | */ 140 | boolean allowPartialUpdateFailed(); 141 | 142 | @NotNull 143 | String getIdKey(); 144 | @NotNull 145 | String getUserIdKey(); 146 | 147 | 148 | /**获取数据库版本号,可通过判断版本号解决一些 JDBC 驱动连接数据库的兼容问题 149 | * MYSQL: 8.0, 5.7, 5.6 等; PostgreSQL: 11, 10, 9.6 等 150 | * @return 151 | */ 152 | String gainDBVersion(); 153 | 154 | @NotNull 155 | default int[] gainDBVersionNums() { 156 | String dbVersion = StringUtil.noBlank(gainDBVersion()); 157 | if (dbVersion.isEmpty()) { 158 | return new int[]{0}; 159 | } 160 | 161 | int index = dbVersion.indexOf("-"); 162 | if (index > 0) { 163 | dbVersion = dbVersion.substring(0, index); 164 | } 165 | 166 | String[] ss = dbVersion.split("[.]"); 167 | int[] nums = new int[Math.max(1, ss.length)]; 168 | for (int i = 0; i < ss.length; i++) { 169 | nums[i] = Integer.valueOf(ss[i]); 170 | } 171 | 172 | return nums; 173 | } 174 | 175 | /**获取数据库地址 176 | * @return 177 | */ 178 | String gainDBUri(); 179 | 180 | /**获取数据库账号 181 | * @return 182 | */ 183 | String gainDBAccount(); 184 | 185 | /**获取数据库密码 186 | * @return 187 | */ 188 | String gainDBPassword(); 189 | 190 | /**获取SQL语句 191 | * @return 192 | * @throws Exception 193 | */ 194 | String gainSQL(boolean prepared) throws Exception; 195 | 196 | 197 | 198 | boolean isTest(); 199 | SQLConfig setTest(boolean test); 200 | 201 | int getType(); 202 | SQLConfig setType(int type); 203 | 204 | int getCount(); 205 | SQLConfig setCount(int count); 206 | 207 | int getPage(); 208 | SQLConfig setPage(int page); 209 | 210 | int getQuery(); 211 | SQLConfig setQuery(int query); 212 | 213 | Boolean getCompat(); 214 | SQLConfig setCompat(Boolean compat); 215 | 216 | int getPosition(); 217 | SQLConfig setPosition(int position); 218 | 219 | int getCache(); 220 | SQLConfig setCache(int cache); 221 | 222 | boolean isExplain(); 223 | SQLConfig setExplain(boolean explain); 224 | 225 | 226 | RequestMethod getMethod(); 227 | SQLConfig setMethod(RequestMethod method); 228 | 229 | Object getId(); 230 | SQLConfig setId(Object id); 231 | 232 | Object getIdIn(); 233 | SQLConfig setIdIn(Object idIn); 234 | 235 | Object getUserId(); 236 | SQLConfig setUserId(Object userId); 237 | 238 | Object getUserIdIn(); 239 | SQLConfig setUserIdIn(Object userIdIn); 240 | 241 | String getRole(); 242 | SQLConfig setRole(String role); 243 | 244 | public boolean isDistinct(); 245 | public SQLConfig setDistinct(boolean distinct); 246 | 247 | String getDatabase(); 248 | SQLConfig setDatabase(String database); 249 | 250 | String getSQLNamespace(); 251 | String getNamespace(); 252 | SQLConfig setNamespace(String namespace); 253 | 254 | String gainSQLCatalog(); 255 | String getCatalog(); 256 | SQLConfig setCatalog(String catalog); 257 | 258 | String gainSQLSchema(); 259 | String getSchema(); 260 | SQLConfig setSchema(String schema); 261 | 262 | String getDatasource(); 263 | SQLConfig setDatasource(String datasource); 264 | 265 | String getQuote(); 266 | 267 | List getJson(); 268 | SQLConfig setJson(List json); 269 | 270 | /**请求传进来的Table名 271 | * @return 272 | * @see {@link #gainSQLTable()} 273 | */ 274 | String getTable(); 275 | 276 | SQLConfig setTable(String table); 277 | 278 | /**数据库里的真实Table名 279 | * 通过 {@link AbstractSQLConfig.TABLE_KEY_MAP} 映射 280 | * @return 281 | */ 282 | String gainSQLTable(); 283 | 284 | String gainTablePath(); 285 | 286 | Map getKeyMap(); 287 | SQLConfig setKeyMap(Map keyMap); 288 | 289 | List getRaw(); 290 | SQLConfig setRaw(List raw); 291 | 292 | Subquery getFrom(); 293 | SQLConfig setFrom(Subquery from); 294 | 295 | List getColumn(); 296 | SQLConfig setColumn(List column); 297 | 298 | List> getValues(); 299 | SQLConfig setValues(List> values); 300 | 301 | Map getContent(); 302 | SQLConfig setContent(Map content); 303 | 304 | Map> getCombineMap(); 305 | SQLConfig setCombineMap(Map> combineMap); 306 | 307 | String getCombine(); 308 | SQLConfig setCombine(String combine); 309 | 310 | Map getCast(); 311 | SQLConfig setCast(Map cast); 312 | 313 | List getNull(); 314 | SQLConfig setNull(List nulls); 315 | 316 | Map getWhere(); 317 | SQLConfig setWhere(Map where); 318 | 319 | String getGroup(); 320 | SQLConfig setGroup(String group); 321 | 322 | Map getHaving(); 323 | SQLConfig setHaving(Map having); 324 | 325 | String getHavingCombine(); 326 | SQLConfig setHavingCombine(String havingCombine); 327 | 328 | String getSample(); 329 | SQLConfig setSample(String order); 330 | 331 | String getLatest(); 332 | SQLConfig setLatest(String latest); 333 | 334 | String getPartition(); 335 | SQLConfig setPartition(String partition); 336 | 337 | String getFill(); 338 | SQLConfig setFill(String fill); 339 | 340 | String getOrder(); 341 | SQLConfig setOrder(String order); 342 | 343 | /** 344 | * exactMatch = false 345 | * @param key 346 | * @return 347 | */ 348 | Object getWhere(String key); 349 | /** 350 | * @param key 351 | * @param exactMatch 352 | * @return 353 | */ 354 | Object getWhere(String key, boolean exactMatch); 355 | /** 356 | * @param key 357 | * @param value 358 | * @return 359 | */ 360 | SQLConfig putWhere(String key, Object value, boolean prior); 361 | 362 | 363 | boolean isPrepared(); 364 | 365 | SQLConfig setPrepared(boolean prepared); 366 | 367 | boolean isMain(); 368 | 369 | SQLConfig setMain(boolean main); 370 | 371 | 372 | List getPreparedValueList(); 373 | SQLConfig setPreparedValueList(List preparedValueList); 374 | 375 | 376 | String getAlias(); 377 | 378 | SQLConfig setAlias(String alias); 379 | 380 | default String gainTableKey() { 381 | String alias = getAlias(); 382 | return getTable() + (StringUtil.isEmpty(alias) ? "" : ":" + alias); 383 | } 384 | 385 | default String gainSQLAlias() { 386 | return gainSQLAlias(getTable(), getAlias()); 387 | } 388 | static String gainSQLAlias(@NotNull String table, String alias) { 389 | // 这里不用 : $ 等符号,因为部分数据库/引擎似乎不支持 `key`, "key", [key] 等避免关键词冲突的方式,只能使用符合变量命名的表别名 390 | return StringUtil.isEmpty(alias) ? table : table + "__" + alias; // 带上原表名,避免 alias 和其它表名/字段名冲突 391 | } 392 | 393 | 394 | String gainWhereString(boolean hasPrefix) throws Exception; 395 | 396 | String gainRawSQL(String key, Object value) throws Exception; 397 | String gainRawSQL(String key, Object value, boolean throwWhenMissing) throws Exception; 398 | 399 | boolean isKeyPrefix(); 400 | 401 | SQLConfig setKeyPrefix(boolean keyPrefix); 402 | 403 | List> getJoinList(); 404 | SQLConfig setJoinList(List> joinList); 405 | 406 | boolean hasJoin(); 407 | 408 | 409 | String gainSubqueryString(Subquery subquery) throws Exception; 410 | 411 | SQLConfig setProcedure(String procedure); 412 | 413 | 414 | List getWithAsExprPreparedValueList(); 415 | SQLConfig setWithAsExprPreparedValueList(List withAsExprePreparedValueList); 416 | 417 | boolean isFakeDelete(); 418 | 419 | Map onFakeDelete(Map map); 420 | 421 | } 422 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/SQLCreator.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import apijson.NotNull; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | /**SQL相关创建器 14 | * @author Lemon 15 | */ 16 | public interface SQLCreator, L extends List> { 17 | 18 | @NotNull 19 | SQLConfig createSQLConfig(); 20 | 21 | @NotNull 22 | SQLExecutor createSQLExecutor(); 23 | } 24 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/SQLExecutor.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.sql.Connection; 9 | import java.sql.ResultSet; 10 | import java.sql.ResultSetMetaData; 11 | import java.sql.SQLException; 12 | import java.sql.Savepoint; 13 | import java.sql.Statement; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | import apijson.*; 18 | 19 | /**executor for query(read) or update(write) MySQL database 20 | * @author Lemon 21 | */ 22 | public interface SQLExecutor, L extends List> { 23 | Parser getParser(); 24 | SQLExecutor setParser(Parser parser); 25 | 26 | /**保存缓存 27 | * @param sql 28 | * @param list 29 | * @param config 30 | */ 31 | void putCache(String sql, List list, SQLConfig config); 32 | 33 | /**获取缓存 34 | * @param sql 35 | * @param config 36 | * @return 37 | */ 38 | List getCache(String sql, SQLConfig config); 39 | 40 | /**获取缓存 41 | * @param sql 42 | * @param position 43 | * @param config 44 | * @return 45 | */ 46 | M getCacheItem(String sql, int position, SQLConfig config); 47 | 48 | /**移除缓存 49 | * @param sql 50 | * @param config 51 | */ 52 | void removeCache(String sql, SQLConfig config); 53 | 54 | /**执行SQL 55 | * @param config 56 | * @param unknownType 57 | * @return 58 | * @throws Exception 59 | */ 60 | M execute(@NotNull SQLConfig config, boolean unknownType) throws Exception; 61 | 62 | //executeQuery和executeUpdate这两个函数因为返回类型不同,所以不好合并 63 | /**执行查询 64 | * @param config 65 | * @return 66 | * @throws SQLException 67 | */ 68 | default ResultSet executeQuery(@NotNull SQLConfig config) throws Exception { 69 | return executeQuery(config, null); 70 | } 71 | ResultSet executeQuery(@NotNull SQLConfig config, String sql) throws Exception; 72 | 73 | /**执行增、删、改 74 | * @param config 75 | * @return 76 | * @throws SQLException 77 | */ 78 | default int executeUpdate(@NotNull SQLConfig config) throws Exception { 79 | return executeUpdate(config, null); 80 | } 81 | int executeUpdate(@NotNull SQLConfig config, String sql) throws Exception; 82 | 83 | 84 | /**判断是否为JSON类型 85 | * @param config 86 | * @param rsmd 87 | * @param position 88 | * @param label 89 | * @return 90 | */ 91 | boolean isJSONType(@NotNull SQLConfig config, ResultSetMetaData rsmd, int position, String label); 92 | 93 | 94 | Connection getConnection(@NotNull SQLConfig config) throws Exception; 95 | default Statement getStatement(@NotNull SQLConfig config) throws Exception { 96 | return getStatement(config, null); 97 | } 98 | Statement getStatement(@NotNull SQLConfig config, String sql) throws Exception; 99 | 100 | int getTransactionIsolation(); 101 | void setTransactionIsolation(int transactionIsolation); 102 | /**开始事务 103 | * @throws SQLException 104 | */ 105 | void begin(int transactionIsolation) throws SQLException; 106 | /**回滚事务 107 | * @throws SQLException 108 | */ 109 | void rollback() throws SQLException; 110 | /**提交事务 111 | * @throws SQLException 112 | */ 113 | void rollback(Savepoint savepoint) throws SQLException; 114 | /**提交事务 115 | * @throws SQLException 116 | */ 117 | void commit() throws SQLException; 118 | /**关闭连接,释放资源 119 | */ 120 | void close(); 121 | 122 | ResultSet executeQuery(@NotNull Statement statement, String sql) throws Exception; 123 | 124 | int executeUpdate(@NotNull Statement statement, String sql) throws Exception; 125 | 126 | ResultSet execute(@NotNull Statement statement, String sql) throws Exception; 127 | 128 | int getGeneratedSQLCount(); 129 | 130 | int getCachedSQLCount(); 131 | 132 | int getExecutedSQLCount(); 133 | 134 | long getExecutedSQLDuration(); 135 | 136 | long getSqlResultDuration(); 137 | 138 | } 139 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/Subquery.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /**子查询 配置 12 | * @author Lemon 13 | */ 14 | public class Subquery, L extends List> { 15 | 16 | private String path; // []/0/User 17 | private String originKey; //id{}@ 18 | private M originValue; // { "from": "Comment", "Comment": {...} } 19 | 20 | private String from; // Comment 21 | private String range; // ANY, ALL 22 | private String key; //id{} 23 | private SQLConfig config; 24 | 25 | public String gainPath() { 26 | return path; 27 | } 28 | public void setPath(String path) { 29 | this.path = path; 30 | } 31 | 32 | public String gainOriginKey() { 33 | return originKey; 34 | } 35 | public void setOriginKey(String originKey) { 36 | this.originKey = originKey; 37 | } 38 | 39 | public M gainOriginValue() { 40 | return originValue; 41 | } 42 | public void setOriginValue(M originValue) { 43 | this.originValue = originValue; 44 | } 45 | 46 | public String gainFrom() { 47 | return from; 48 | } 49 | public void setFrom(String from) { 50 | this.from = from; 51 | } 52 | 53 | public String gainRange() { 54 | return range; 55 | } 56 | public void setRange(String range) { 57 | this.range = range; 58 | } 59 | 60 | public String gainKey() { 61 | return key; 62 | } 63 | public void setKey(String key) { 64 | this.key = key; 65 | } 66 | 67 | public SQLConfig gainConfig() { 68 | return config; 69 | } 70 | public void setConfig(SQLConfig config) { 71 | this.config = config; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/Verifier.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import apijson.*; 12 | 13 | /**校验器(权限、请求参数、返回结果等) 14 | * @author Lemon 15 | */ 16 | public interface Verifier, L extends List> { 17 | 18 | 19 | /**验证权限是否通过 20 | * @param config 21 | * @return 22 | * @throws Exception 23 | */ 24 | boolean verifyAccess(SQLConfig config) throws Exception; 25 | 26 | 27 | /**校验请求使用的角色,角色不好判断,让访问者发过来角色名,OWNER,CONTACT,ADMIN等 28 | * @param config 29 | * @param table 30 | * @param method 31 | * @param role 32 | * @return 33 | * @throws Exception 34 | * @see {@link JSONMap#KEY_ROLE} 35 | */ 36 | void verifyRole(SQLConfig config, String table, RequestMethod method, String role) throws Exception; 37 | 38 | /**登录校验 39 | * @throws Exception 40 | */ 41 | void verifyLogin() throws Exception; 42 | /**管理员角色校验 43 | * @throws Exception 44 | */ 45 | void verifyAdmin() throws Exception; 46 | 47 | 48 | 49 | /**验证是否重复 50 | * @param table 51 | * @param key 52 | * @param value 53 | * @throws Exception 54 | */ 55 | void verifyRepeat(String table, String key, Object value) throws Exception; 56 | 57 | /**验证是否重复 58 | * @param table 59 | * @param key 60 | * @param value 61 | * @param exceptId 不包含id 62 | * @throws Exception 63 | */ 64 | void verifyRepeat(String table, String key, Object value, long exceptId) throws Exception; 65 | 66 | /**验证请求参数的数据和结构 67 | * @param method 68 | * @param name 69 | * @param target 70 | * @param request 71 | * @param maxUpdateCount 72 | * @param globalDatabase 73 | * @param globalSchema 74 | * @param creator 75 | * @return 76 | * @throws Exception 77 | */ 78 | M verifyRequest(RequestMethod method, String name, M target, M request, 79 | int maxUpdateCount, String globalDatabase, String globalSchema) throws Exception; 80 | 81 | /**验证返回结果的数据和结构 82 | * @param method 83 | * @param name 84 | * @param target 85 | * @param response 86 | * @param database 87 | * @param schema 88 | * @param creator 89 | * @param callback 90 | * @return 91 | * @throws Exception 92 | */ 93 | M verifyResponse( 94 | RequestMethod method, String name, M target, M response, 95 | String database, String schema, @NotNull Parser parser, OnParseCallback callback 96 | ) throws Exception; 97 | 98 | 99 | @NotNull 100 | Parser createParser(); 101 | 102 | Parser getParser(); 103 | Verifier setParser(AbstractParser parser); 104 | 105 | @NotNull 106 | Visitor getVisitor(); 107 | Verifier setVisitor(@NotNull Visitor visitor); 108 | 109 | String getVisitorIdKey(SQLConfig config); 110 | 111 | } 112 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/VerifierCreator.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import apijson.NotNull; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | /**验证器相关创建器 14 | * @author Lemon 15 | */ 16 | public interface VerifierCreator, L extends List> { 17 | 18 | @NotNull 19 | Verifier createVerifier(); 20 | } 21 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/Visitor.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm; 7 | 8 | import java.util.List; 9 | 10 | /**来访者 11 | * @author Lemon 12 | */ 13 | public interface Visitor { 14 | 15 | T getId(); 16 | 17 | List getContactIdList(); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/exception/CommonException.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.exception; 7 | 8 | import java.io.UnsupportedEncodingException; 9 | import java.net.HttpRetryException; 10 | import java.sql.SQLException; 11 | import java.util.concurrent.TimeoutException; 12 | 13 | import apijson.JSONResponse; 14 | import apijson.Log; 15 | import apijson.StringUtil; 16 | import apijson.orm.AbstractSQLConfig; 17 | import apijson.orm.SQLConfig; 18 | 19 | /**异常包装器,主要用来包装构造器没有 Throwable 参数的 Exception 20 | * @author Lemon 21 | */ 22 | public class CommonException extends Exception { 23 | private static final long serialVersionUID = 1L; 24 | private Integer code; 25 | private String environment; 26 | 27 | public CommonException setCode(Integer code) { 28 | this.code = code; 29 | return this; 30 | } 31 | public Integer getCode() { 32 | if (code == null) { 33 | code = getCode(getCause()); 34 | } 35 | return code; 36 | } 37 | 38 | 39 | public static int getCode(Throwable e) { 40 | boolean isCommon = Log.DEBUG && e instanceof CommonException; 41 | 42 | Integer code = isCommon ? ((CommonException) e).getCode() : null; 43 | if (code != null) { 44 | return code; 45 | } 46 | 47 | Throwable t = isCommon ? e.getCause() : e; 48 | if (t == null) { 49 | return JSONResponse.CODE_SERVER_ERROR; 50 | } 51 | 52 | if (t instanceof HttpRetryException) { 53 | return ((HttpRetryException) t).responseCode(); 54 | } 55 | 56 | if (t instanceof UnsupportedEncodingException) { 57 | return JSONResponse.CODE_UNSUPPORTED_ENCODING; 58 | } 59 | 60 | if (t instanceof IllegalAccessException) { 61 | return JSONResponse.CODE_ILLEGAL_ACCESS; 62 | } 63 | 64 | if (t instanceof UnsupportedOperationException) { 65 | return JSONResponse.CODE_UNSUPPORTED_OPERATION; 66 | } 67 | 68 | if (t instanceof NotExistException) { 69 | return JSONResponse.CODE_NOT_FOUND; 70 | } 71 | 72 | if (t instanceof IllegalArgumentException) { 73 | return JSONResponse.CODE_ILLEGAL_ARGUMENT; 74 | } 75 | 76 | if (t instanceof NotLoggedInException) { 77 | return JSONResponse.CODE_NOT_LOGGED_IN; 78 | } 79 | 80 | if (t instanceof TimeoutException) { 81 | return JSONResponse.CODE_TIME_OUT; 82 | } 83 | 84 | if (t instanceof ConflictException) { 85 | return JSONResponse.CODE_CONFLICT; 86 | } 87 | 88 | if (t instanceof ConditionErrorException) { 89 | return JSONResponse.CODE_CONDITION_ERROR; 90 | } 91 | 92 | if (t instanceof UnsupportedDataTypeException) { 93 | return JSONResponse.CODE_UNSUPPORTED_TYPE; 94 | } 95 | 96 | if (t instanceof OutOfRangeException) { 97 | return JSONResponse.CODE_OUT_OF_RANGE; 98 | } 99 | 100 | if (t instanceof NullPointerException) { 101 | return JSONResponse.CODE_NULL_POINTER; 102 | } 103 | 104 | return JSONResponse.CODE_SERVER_ERROR; 105 | } 106 | 107 | public static String getMsg(Throwable e) { 108 | if (e == null) { 109 | return null; 110 | } 111 | 112 | String msg = e.getMessage(); 113 | if (msg != null) { 114 | return msg; 115 | } 116 | 117 | Throwable t = e.getCause(); 118 | return t == null ? null : t.getMessage(); 119 | } 120 | 121 | public CommonException setEnvironment(String environment) { 122 | this.environment = environment; 123 | return this; 124 | } 125 | 126 | public String getEnvironment() { 127 | return environment; 128 | } 129 | 130 | public CommonException(Throwable t) { 131 | this(null, t); 132 | } 133 | public CommonException(String msg, Throwable t) { 134 | super(msg == null && t != null ? t.getMessage() : null, t); 135 | } 136 | 137 | public CommonException(int code, String msg) { 138 | this(code, msg, null); 139 | } 140 | public CommonException(int code, String msg, Throwable t) { 141 | this(msg, t); 142 | setCode(code); 143 | } 144 | public CommonException(Throwable t, String environment) { 145 | this(null, t); 146 | setEnvironment(environment); 147 | } 148 | 149 | 150 | public static Exception wrap(Exception e, SQLConfig config) { 151 | if (Log.DEBUG == false && e instanceof SQLException) { 152 | return new SQLException("数据库驱动执行异常SQLException,非 Log.DEBUG 模式下不显示详情,避免泄漏真实模式名、表名等隐私信息", e); 153 | } 154 | 155 | // String msg = e.getMessage(); 156 | 157 | if (Log.DEBUG && (e instanceof CommonException == false || ((CommonException) e).getEnvironment() == null)) { 158 | // msg != null && msg.contains(Log.KEY_SYSTEM_INFO_DIVIDER) == false) { 159 | try { 160 | String db = config == null ? AbstractSQLConfig.DEFAULT_DATABASE : (config instanceof AbstractSQLConfig 161 | ? ((AbstractSQLConfig) config).gainSQLDatabase() : config.getDatabase() 162 | ); 163 | 164 | String dbVersion = config == null ? null : config.gainDBVersion(); 165 | if (StringUtil.isEmpty(dbVersion)) { 166 | dbVersion = ""; 167 | } 168 | 169 | if (db != null || config == null) { 170 | db += " " + dbVersion; 171 | } 172 | else if (config.isMySQL()) { 173 | db = SQLConfig.DATABASE_MYSQL + " " + dbVersion; 174 | } 175 | else if (config.isMariaDB()) { 176 | db = SQLConfig.DATABASE_MARIADB + " " + dbVersion; 177 | } 178 | else if (config.isTiDB()) { 179 | db = SQLConfig.DATABASE_TIDB + " " + dbVersion; 180 | } 181 | else if (config.isPostgreSQL()) { 182 | db = SQLConfig.DATABASE_POSTGRESQL + " " + dbVersion; 183 | } 184 | else if (config.isCockroachDB()) { 185 | db = SQLConfig.DATABASE_COCKROACHDB + " " + dbVersion; 186 | } 187 | else if (config.isSQLServer()) { 188 | db = SQLConfig.DATABASE_SQLSERVER + " " + dbVersion; 189 | } 190 | else if (config.isOracle()) { 191 | db = SQLConfig.DATABASE_ORACLE + " " + dbVersion; 192 | } 193 | else if (config.isDb2()) { 194 | db = SQLConfig.DATABASE_DB2 + " " + dbVersion; 195 | } 196 | else if (config.isDuckDB()) { 197 | db = SQLConfig.DATABASE_DUCKDB + " " + dbVersion; 198 | } 199 | else if (config.isSurrealDB()) { 200 | db = SQLConfig.DATABASE_SURREALDB + " " + dbVersion; 201 | } 202 | else if (config.isOpenGauss()) { 203 | db = SQLConfig.DATABASE_OPENGAUSS + " " + dbVersion; 204 | } 205 | else if (config.isDameng()) { 206 | db = SQLConfig.DATABASE_DAMENG + " " + dbVersion; 207 | } 208 | else if (config.isKingBase()) { 209 | db = SQLConfig.DATABASE_KINGBASE + " " + dbVersion; 210 | } 211 | else if (config.isElasticsearch()) { 212 | db = SQLConfig.DATABASE_ELASTICSEARCH + " " + dbVersion; 213 | } 214 | else if (config.isManticore()) { 215 | db = SQLConfig.DATABASE_MANTICORE + " " + dbVersion; 216 | } 217 | else if (config.isClickHouse()) { 218 | db = SQLConfig.DATABASE_CLICKHOUSE + " " + dbVersion; 219 | } 220 | else if (config.isMilvus()) { 221 | db = SQLConfig.DATABASE_MILVUS + " " + dbVersion; 222 | } 223 | else if (config.isInfluxDB()) { 224 | db = SQLConfig.DATABASE_INFLUXDB + " " + dbVersion; 225 | } 226 | else if (config.isTDengine()) { 227 | db = SQLConfig.DATABASE_TDENGINE + " " + dbVersion; 228 | } 229 | else if (config.isTimescaleDB()) { 230 | db = SQLConfig.DATABASE_TIMESCALEDB + " " + dbVersion; 231 | } 232 | else if (config.isQuestDB()) { 233 | db = SQLConfig.DATABASE_QUESTDB + " " + dbVersion; 234 | } 235 | else if (config.isIoTDB()) { 236 | db = SQLConfig.DATABASE_IOTDB + " " + dbVersion; 237 | } 238 | else if (config.isSQLite()) { 239 | db = SQLConfig.DATABASE_SQLITE + " " + dbVersion; 240 | } 241 | else if (config.isHive()) { 242 | db = SQLConfig.DATABASE_HIVE + " " + dbVersion; 243 | } 244 | else if (config.isPresto()) { 245 | db = SQLConfig.DATABASE_PRESTO + " " + dbVersion; 246 | } 247 | else if (config.isTrino()) { 248 | db = SQLConfig.DATABASE_TRINO + " " + dbVersion; 249 | } 250 | else if (config.isDoris()) { 251 | db = SQLConfig.DATABASE_DORIS + " " + dbVersion; 252 | } 253 | else if (config.isSnowflake()) { 254 | db = SQLConfig.DATABASE_SNOWFLAKE + " " + dbVersion; 255 | } 256 | else if (config.isDatabricks()) { 257 | db = SQLConfig.DATABASE_DATABRICKS + " " + dbVersion; 258 | } 259 | else if (config.isMongoDB()) { 260 | db = SQLConfig.DATABASE_MONGODB + " " + dbVersion; 261 | } 262 | else if (config.isCassandra()) { 263 | db = SQLConfig.DATABASE_CASSANDRA + " " + dbVersion; 264 | } 265 | else if (config.isRedis()) { 266 | db = SQLConfig.DATABASE_REDIS + " " + dbVersion; 267 | } 268 | else if (config.isKafka()) { 269 | db = SQLConfig.DATABASE_KAFKA + " " + dbVersion; 270 | } 271 | else { 272 | db = ""; 273 | } 274 | 275 | // Class clazz = e.getClass(); 276 | // msg = msg 277 | // + " " + Log.KEY_SYSTEM_INFO_DIVIDER + " **环境信息** " 278 | String env = " **环境信息** " 279 | + " \n 系统: " + Log.OS_NAME + " " + Log.OS_VERSION 280 | + " \n 数据库: " + db 281 | + " \n JDK: " + Log.JAVA_VERSION + " " + Log.OS_ARCH 282 | + " \n APIJSON: " + Log.VERSION; 283 | 284 | if (e instanceof CommonException) { 285 | ((CommonException) e).setEnvironment(env); 286 | return e; 287 | } 288 | 289 | // try { 290 | // e = clazz.getConstructor(String.class, Throwable.class).newInstance(msg, e); 291 | // } 292 | // catch (Throwable e2) { 293 | return new CommonException(e, env); // e = clazz.getConstructor(String.class).newInstance(msg); 294 | // } 295 | } catch (Throwable e2) {} 296 | } 297 | 298 | return e; 299 | } 300 | 301 | } 302 | 303 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/exception/ConditionErrorException.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.exception; 7 | 8 | /**条件错误 9 | * @author Lemon 10 | */ 11 | public class ConditionErrorException extends Exception { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public ConditionErrorException(String msg) { 15 | super(msg); 16 | } 17 | public ConditionErrorException(Throwable t) { 18 | super(t); 19 | } 20 | public ConditionErrorException(String msg, Throwable t) { 21 | super(msg, t); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/exception/ConflictException.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.exception; 7 | 8 | /**冲突 9 | * @author Lemon 10 | */ 11 | public class ConflictException extends Exception { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public ConflictException(String msg) { 15 | super(msg); 16 | } 17 | public ConflictException(Throwable t) { 18 | super(t); 19 | } 20 | public ConflictException(String msg, Throwable t) { 21 | super(msg, t); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/exception/NotExistException.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.exception; 7 | 8 | /**不存在,可接受,内部吃掉 9 | * @author Lemon 10 | */ 11 | public class NotExistException extends Exception { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public NotExistException(String msg) { 15 | super(msg); 16 | } 17 | public NotExistException(Throwable t) { 18 | super(t); 19 | } 20 | public NotExistException(String msg, Throwable t) { 21 | super(msg, t); 22 | } 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/exception/NotLoggedInException.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.exception; 7 | 8 | /**未登录 9 | * @author Lemon 10 | */ 11 | public class NotLoggedInException extends Exception { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public NotLoggedInException(String msg, Throwable t) { 15 | super(msg, t); 16 | } 17 | public NotLoggedInException(String msg) { 18 | super(msg); 19 | } 20 | public NotLoggedInException(Throwable t) { 21 | super(t); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/exception/OutOfRangeException.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.exception; 7 | 8 | /**超出范围 9 | * @author Lemon 10 | */ 11 | public class OutOfRangeException extends Exception { 12 | private static final long serialVersionUID = 1L; 13 | 14 | public OutOfRangeException(String msg) { 15 | super(msg); 16 | } 17 | public OutOfRangeException(Throwable t) { 18 | super(t); 19 | } 20 | public OutOfRangeException(String msg, Throwable t) { 21 | super(msg, t); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/exception/UnsupportedDataTypeException.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.exception; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | * 给定的数据类型不被支持 12 | * 13 | * @author cnscoo 14 | */ 15 | 16 | public class UnsupportedDataTypeException extends IOException { 17 | private static final long serialVersionUID = 1L; 18 | 19 | public UnsupportedDataTypeException() { 20 | super(); 21 | } 22 | 23 | public UnsupportedDataTypeException(String s) { 24 | super(s); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/exception/package-info.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | /** 7 | * exception files package 8 | */ 9 | /** 10 | * @author Lemon 11 | * 12 | */ 13 | package apijson.orm.exception; -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/Access.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**访问权限 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class Access { 15 | } -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/AllColumn.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**SQL Server 在 sys 下的字段(列名) 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class AllColumn { 15 | public static final String TAG = "AllColumn"; 16 | public static final String TABLE_NAME = "ALL_TAB_COLUMNS"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/AllColumnComment.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**SQL Server 在 sys 下的字段(列名) 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class AllColumnComment { 15 | public static final String TAG = "AllColumnComment"; 16 | public static final String TABLE_NAME = "ALL_COL_COMMENTS"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/AllTable.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**SQL Server 表属性 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class AllTable { 15 | public static final String TAG = "AllTable"; 16 | public static final String TABLE_NAME = "ALL_TABLES"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/AllTableComment.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**SQL Server 表属性 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class AllTableComment { 15 | public static final String TAG = "AllTableComment"; 16 | public static final String TABLE_NAME = "ALL_TAB_COMMENTS"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/Column.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**字段(列名)属性 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class Column { 15 | public static final String TAG = "Column"; 16 | public static final String TABLE_NAME = "columns"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/Document.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import static apijson.orm.AbstractVerifier.ADMIN; 9 | import static apijson.orm.AbstractVerifier.LOGIN; 10 | 11 | import java.io.Serializable; 12 | import java.sql.Timestamp; 13 | 14 | import apijson.MethodAccess; 15 | 16 | /**测试用例文档 17 | * @author Lemon 18 | */ 19 | @MethodAccess( 20 | GET = { LOGIN, ADMIN }, 21 | HEAD = { LOGIN, ADMIN }, 22 | PUT = { LOGIN, ADMIN } 23 | ) 24 | public class Document implements Serializable { 25 | private static final long serialVersionUID = 1L; 26 | 27 | private Long id; //唯一标识 28 | private Long userId; //用户id 应该用adminId,只有当登录账户是管理员时才能操作文档。 需要先建Admin表,新增登录等相关接口。 29 | private Integer version; //接口版本号 <=0 - 不限制版本,任意版本都可用这个接口 >0 - 在这个版本添加的接口 30 | private String name; //接口名称 31 | private String url; //请求地址 32 | private String request; //请求 用json格式会导致强制排序,而请求中引用赋值只能引用上面的字段,必须有序。 33 | private Timestamp date; //创建日期 34 | private String response; //标准返回结果 35 | 36 | 37 | public Document() { 38 | super(); 39 | } 40 | public Document(long id) { 41 | this(); 42 | setId(id); 43 | } 44 | 45 | 46 | 47 | 48 | public Long getId() { 49 | return id; 50 | } 51 | 52 | public Document setId(Long id) { 53 | this.id = id; 54 | return this; 55 | } 56 | 57 | public Long getUserId() { 58 | return userId; 59 | } 60 | 61 | public Document setUserId(Long userId) { 62 | this.userId = userId; 63 | return this; 64 | } 65 | 66 | public Integer getVersion() { 67 | return version; 68 | } 69 | 70 | public Document setVersion(Integer version) { 71 | this.version = version; 72 | return this; 73 | } 74 | 75 | public String getName() { 76 | return name; 77 | } 78 | 79 | public Document setName(String name) { 80 | this.name = name; 81 | return this; 82 | } 83 | 84 | public String getUrl() { 85 | return url; 86 | } 87 | 88 | public Document setUrl(String url) { 89 | this.url = url; 90 | return this; 91 | } 92 | 93 | public String getRequest() { 94 | return request; 95 | } 96 | 97 | public Document setRequest(String request) { 98 | this.request = request; 99 | return this; 100 | } 101 | 102 | public Timestamp getDate() { 103 | return date; 104 | } 105 | 106 | public Document setDate(Timestamp date) { 107 | this.date = date; 108 | return this; 109 | } 110 | 111 | public String getResponse() { 112 | return response; 113 | } 114 | 115 | public Document setResponse(String response) { 116 | this.response = response; 117 | return this; 118 | } 119 | 120 | 121 | } -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/ExtendedProperty.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**扩展属性,SQL Server 转用 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class ExtendedProperty { 15 | public static final String TAG = "ExtendedProperty"; 16 | public static final String TABLE_NAME = "extended_properties"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/Function.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**远程函数 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class Function { 15 | } -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/PgAttribute.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**PostgreSQL 字段属性 11 | * @author Lemon 12 | */ 13 | @MethodAccess 14 | public class PgAttribute { 15 | public static final String TAG = "PgAttribute"; 16 | public static final String TABLE_NAME = "pg_attribute"; 17 | 18 | } -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/PgClass.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**PostgreSQL 表属性 11 | * @author Lemon 12 | */ 13 | @MethodAccess 14 | public class PgClass { 15 | public static final String TAG = "PgClass"; 16 | public static final String TABLE_NAME = "pg_class"; 17 | 18 | } -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/Request.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**请求处理 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class Request { 15 | } 16 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/Script.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**代码脚本 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class Script { 15 | } -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/SysColumn.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**SQL Server 在 sys 下的字段(列名) 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class SysColumn { 15 | public static final String TAG = "SysColumn"; 16 | public static final String TABLE_NAME = "columns"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/SysTable.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**SQL Server 表属性 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class SysTable { 15 | public static final String TAG = "SysTable"; 16 | public static final String TABLE_NAME = "tables"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/Table.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import apijson.MethodAccess; 9 | 10 | /**表属性 11 | * @author Lemon 12 | */ 13 | @MethodAccess(POST = {}, PUT = {}, DELETE = {}) 14 | public class Table { 15 | public static final String TAG = "Table"; 16 | public static final String TABLE_NAME = "tables"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/TestRecord.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | package apijson.orm.model; 7 | 8 | import static apijson.orm.AbstractVerifier.ADMIN; 9 | import static apijson.orm.AbstractVerifier.LOGIN; 10 | 11 | import java.io.Serializable; 12 | import java.sql.Timestamp; 13 | 14 | import apijson.MethodAccess; 15 | 16 | /**测试结果。5.0.0 之后可能改名为 Test 17 | * @author Lemon 18 | */ 19 | @MethodAccess(GET = { LOGIN, ADMIN }, HEAD = { LOGIN, ADMIN }) 20 | public class TestRecord implements Serializable { 21 | private static final long serialVersionUID = 1L; 22 | 23 | private Long id; //唯一标识 24 | private Long userId; //用户id 25 | private Long documentId; //测试用例文档id 26 | private Timestamp date; //创建日期 27 | private String compare; //对比结果 28 | private String response; //接口返回结果JSON 用json格式会导致强制排序,而请求中引用赋值只能引用上面的字段,必须有序。 29 | private String standard; //response 的校验标准,是一个 JSON 格式的 AST ,描述了正确 Response 的结构、里面的字段名称、类型、长度、取值范围 等属性。 30 | 31 | 32 | public TestRecord() { 33 | super(); 34 | } 35 | public TestRecord(long id) { 36 | this(); 37 | setId(id); 38 | } 39 | 40 | 41 | 42 | 43 | public Long getId() { 44 | return id; 45 | } 46 | 47 | public TestRecord setId(Long id) { 48 | this.id = id; 49 | return this; 50 | } 51 | 52 | public Long getUserId() { 53 | return userId; 54 | } 55 | 56 | public TestRecord setUserId(Long userId) { 57 | this.userId = userId; 58 | return this; 59 | } 60 | 61 | public Long getDocumentId() { 62 | return documentId; 63 | } 64 | 65 | public TestRecord setDocumentId(Long documentId) { 66 | this.documentId = documentId; 67 | return this; 68 | } 69 | 70 | public Timestamp getDate() { 71 | return date; 72 | } 73 | 74 | public TestRecord setDate(Timestamp date) { 75 | this.date = date; 76 | return this; 77 | } 78 | 79 | public String getCompare() { 80 | return compare; 81 | } 82 | 83 | public TestRecord setCompare(String compare) { 84 | this.compare = compare; 85 | return this; 86 | } 87 | 88 | public String getResponse() { 89 | return response; 90 | } 91 | 92 | public TestRecord setResponse(String response) { 93 | this.response = response; 94 | return this; 95 | } 96 | 97 | public String getStandard() { 98 | return standard; 99 | } 100 | 101 | public TestRecord setStandard(String standard) { 102 | this.standard = standard; 103 | return this; 104 | } 105 | 106 | 107 | } -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/model/package-info.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | /** 7 | * models for special tables 8 | */ 9 | /** 10 | * @author Lemon 11 | * 12 | */ 13 | package apijson.orm.model; -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/package-info.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | /** 7 | * server files package 8 | */ 9 | /** 10 | * @author Lemon 11 | * 12 | */ 13 | package apijson.orm; -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/script/JSR223ScriptExecutor.java: -------------------------------------------------------------------------------- 1 | package apijson.orm.script; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | import javax.script.Bindings; 9 | import javax.script.Compilable; 10 | import javax.script.CompiledScript; 11 | import javax.script.ScriptEngine; 12 | import javax.script.ScriptEngineManager; 13 | import javax.script.SimpleBindings; 14 | 15 | import apijson.orm.AbstractFunctionParser; 16 | 17 | /** 18 | * JSR223 script engine的统一实现抽象类 19 | */ 20 | public abstract class JSR223ScriptExecutor, L extends List> implements ScriptExecutor { 21 | protected ScriptEngine scriptEngine; 22 | 23 | private final Map compiledScriptMap = new ConcurrentHashMap<>(); 24 | 25 | @Override 26 | public ScriptExecutor init() { 27 | ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); 28 | scriptEngine = scriptEngineManager.getEngineByName(scriptEngineName()); 29 | return this; 30 | } 31 | 32 | protected abstract String scriptEngineName(); 33 | 34 | protected abstract Object extendParameter(AbstractFunctionParser parser, Map currentObject, String methodName, Object[] args); 35 | 36 | protected abstract boolean isLockScript(String methodName); 37 | 38 | protected String convertScript(String script) { 39 | return script; 40 | } 41 | 42 | @Override 43 | public void load(String name, String script) { 44 | try { 45 | CompiledScript compiledScript = ((Compilable) scriptEngine).compile(convertScript(script)); 46 | compiledScriptMap.put(name, compiledScript); 47 | } catch (Exception e) { 48 | e.printStackTrace(); 49 | } 50 | 51 | } 52 | 53 | @Override 54 | public Object execute(AbstractFunctionParser parser, Map currentObject, String methodName, Object[] args) throws Exception { 55 | CompiledScript compiledScript = compiledScriptMap.get(methodName); 56 | Bindings bindings = new SimpleBindings(); 57 | // 往脚本上下文里放入元数据 58 | // 把 RequestMethod method, String tag, int version, @NotNull JSONMap request, 59 | // HttpSession session 等参数作为全局参数传进去供脚本使用 60 | 61 | // 加载扩展属性 62 | Object extendParameter = this.extendParameter(parser, currentObject, methodName, args); 63 | if(extendParameter != null) { 64 | bindings.put("extParam", extendParameter); 65 | } 66 | 67 | Map metaMap = new HashMap<>(); 68 | metaMap.put("version", parser == null ? 0 : parser.getVersion()); 69 | metaMap.put("tag", parser == null ? null : parser.getTag()); 70 | metaMap.put("args", args); 71 | bindings.put("_meta", metaMap); 72 | return compiledScript.eval(bindings); 73 | } 74 | 75 | @Override 76 | public void cleanCache() { 77 | compiledScriptMap.clear(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/script/JavaScriptExecutor.java: -------------------------------------------------------------------------------- 1 | package apijson.orm.script; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import apijson.orm.AbstractFunctionParser; 7 | 8 | /** 9 | * JavaScript脚本语言的执行器实现 10 | */ 11 | public class JavaScriptExecutor, L extends List> extends JSR223ScriptExecutor { 12 | 13 | @Override 14 | protected String scriptEngineName() { 15 | return "javascript"; 16 | } 17 | 18 | @Override 19 | protected Object extendParameter(AbstractFunctionParser parser, Map currentObject, String methodName, Object[] args) { 20 | return null; 21 | } 22 | 23 | @Override 24 | protected boolean isLockScript(String methodName) { 25 | return false; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/orm/script/ScriptExecutor.java: -------------------------------------------------------------------------------- 1 | package apijson.orm.script; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import apijson.orm.AbstractFunctionParser; 7 | 8 | public interface ScriptExecutor, L extends List> { 9 | 10 | ScriptExecutor init(); 11 | 12 | void load(String name, String script); 13 | 14 | Object execute(AbstractFunctionParser parser, Map currentObject, String methodName, Object[] args) throws Exception; 15 | 16 | void cleanCache(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /APIJSONORM/src/main/java/apijson/package-info.java: -------------------------------------------------------------------------------- 1 | /*Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. 2 | 3 | This source code is licensed under the Apache License Version 2.0.*/ 4 | 5 | 6 | /** 7 | * the same files for server and client projects 8 | */ 9 | /** 10 | * @author Lemon 11 | * 12 | */ 13 | package apijson; -------------------------------------------------------------------------------- /APIJSONORM/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent/APIJSON/efb4f6a362fd2fb00ff363e0dd1344451b2da87f/APIJSONORM/src/main/resources/application.properties -------------------------------------------------------------------------------- /APIJSON初期构思及实现.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent/APIJSON/efb4f6a362fd2fb00ff363e0dd1344451b2da87f/APIJSON初期构思及实现.docx -------------------------------------------------------------------------------- /APIJSON初期构思及实现.pages: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent/APIJSON/efb4f6a362fd2fb00ff363e0dd1344451b2da87f/APIJSON初期构思及实现.pages -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | 我们提倡您通过提 Issue 和 Pull Request 方式来促进 APIJSON 的发展。 4 | 5 | 6 | ## Acknowledgements 7 | 8 | 非常感谢以下贡献者们对于 APIJSON 本项目做出的贡献: 9 | 10 | - [TommyLemon](https://github.com/TommyLemon)(腾讯工程师,还开源了 APIJSON-Demo, apijson-framework, apijson-column, apijson-router 等) 11 | - [ruoranw](https://github.com/ruoranw)(现居美国洛杉矶,还开源了 APIJSONdocs) 12 | - [zhoulingfengofcd](https://github.com/zhoulingfengofcd) 13 | - [Zerounary](https://github.com/Zerounary)(还开源了 APIJSONParser) 14 | - [fineday009](https://github.com/fineday009)(腾讯工程师,还贡献了 apijson-framework, APIJSON-Demo) 15 | - [vincentCheng](https://github.com/vincentCheng)(还开源了 apijson-doc) 16 | - [justinfengchen](https://github.com/justinfengchen) 17 | - [linlwqq](https://github.com/linlwqq) 18 | - [redcatmiss](https://github.com/redcatmiss)(社保科技工程师) 19 | - [linbren](https://github.com/linbren) 20 | - [jinzhongjian](https://github.com/jinzhongjian) 21 | - [CoolGeo2016](https://github.com/CoolGeo2016) 22 | - [1906522096](https://github.com/1906522096) 23 | - [github-ganyu](https://github.com/github-ganyu) 24 | - [sunxiaoguang](https://github.com/sunxiaoguang)(知乎基础研发架构师) 25 | - [403f](https://github.com/403f) 26 | - [gujiachun](https://github.com/gujiachun) 27 | - [gdjs2](https://github.com/gdjs2)(University of California, Riverside) 28 | - [Rkyzzy](https://github.com/Rkyzzy)(SUSTech, University of California, Berkeley) 29 | - [kxlv2000](https://github.com/kxlv2000)(SUSTech) 30 | - [caohao-go](https://github.com/caohao-go)(腾讯工程师,曾在华为、恒生担任C/C++开发工程师,在wps担任项目经理,在360担任技术专家) 31 | - [Wscats](https://github.com/Wscats)(腾讯工程师、腾讯 AlloyTeam 成员、Tencent Creation Camp 成员、知名技术博主) 32 | - [jun0315](https://github.com/jun0315)(腾讯工程师) 33 | - [JieJo](https://github.com/JieJo) 34 | - [yeyuezhishou](https://github.com/yeyuezhishou)(圆通工程师) 35 | - [kenlig](https://github.com/kenlig)(还开源了 apijsondocs) 36 | - [andream7](https://github.com/andream7)(微软工程师,还开源了 apijson-db2) 37 | - [qiujunlin](https://github.com/qiujunlin)(字节跳动工程师,还开源了 APIJSONDemo) 38 | - [HANXU2018](https://github.com/HANXU2018)(网易工程师,还开源了 APIJSON-DOC) 39 | - [hclown9804](https://github.com/hclown9804) 40 | - [chenyanlann](https://github.com/chenyanlann)(还开源了 APIJSONDemo_ClickHouse) 41 | - [haolingzhang1](https://github.com/haolingzhang1)(腾讯工程师,还开源了 APIJson--demo) 42 | - [jerrylususu](https://github.com/jerrylususu)(还开源了 apijson_todo_demo 和 apijson_role_extend) 43 | - [Dalezee](https://github.com/Dalezee)(还开源了 apijson_camp) 44 | - [aaronlinv](https://github.com/aaronlinv) 45 | - [sy-records](https://github.com/sy-records) 46 | - [Finkyky](https://github.com/Finkyky) 47 | - [ifooling](https://github.com/ifooling) 48 | - [transtone](https://github.com/transtone) 49 | - [AwenJackson](https://github.com/AwenJackson)(上海信息出奇科技有限公司工程师,发布了 3 篇文章) 50 | - [andy19055](https://github.com/andy19055) 51 | - [glennliao](https://github.com/glennliao)(还开源了 [apijson-go](https://github.com/glennliao/apijson-go) 和 [apijson-go-ui](https://github.com/glennliao/apijson-go-ui)) 52 | - [eltociear](https://github.com/eltociear) 53 | - [wb04307201](https://github.com/wb04307201)(还开源了 [apijson-dynamic-datasource](https://github.com/wb04307201/apijson-dynamic-datasource)) 54 | - [cloudAndMonkey](https://github.com/cloudAndMonkey)(还贡献了 apijson-framework, APIJSON-Demo,新增支持了 Redis, Elasticsearch, Kafka, Lua 等并提供了多个 Demo) 55 | - [12345ZMTHL](https://github.com/12345ZMTHL) 56 | - [cnscoo](https://github.com/cnscoo)(阿里云工程师) 57 | - [aninZz](https://github.com/aninZz) 58 | - [leomiaomiao](https://github.com/leomiaomiao) 59 | - [YqxLzx](https://github.com/YqxLzx) 60 | - [hiteshbedre](https://github.com/hiteshbedre) 61 | - [wahowaho](https://github.com/wahowaho) 62 | - [jarrodquan](https://github.com/jarrodquan) 63 | - [gemufeng](https://github.com/gemufeng)(上海麦市工程师) 64 | - [komiblog](https://github.com/komiblog) 65 | - [ostrichManX](https://github.com/ostrichManX) 66 | - [jia199807](https://github.com/jia199807) 67 | - [zxcwindy](https://github.com/zxcwindy) 68 | - [afumu](https://github.com/afumu)(gorm-plus 作者) 69 | - [alittle-yu](https://github.com/alittle-yu) 70 | - [Damon Nicola](https://github.com/Reynold3D) 71 | - [calmcc](https://github.com/calmcc) 72 | - [lindaifeng](https://github.com/lindaifeng) 73 | - [DenineLu](https://github.com/DenineLu)(小红书工程师) 74 | 75 | #### 其中特别致谢:
76 | cloudAndMonkey 提交的 11 个 Commits, 对 APIJSON 做出了 1,496 增加和 845 处删减(截止 2022/12/15 日);
77 | justinfengchen 提交的 6 个 Commits, 对 APIJSON 做出了 3,130 增加和 0 处删减(截止 2020/11/04 日);
78 | ruoranw 提交的 18 个 Commits, 对 APIJSON 做出了 328 增加和 520 处删减(截止 2020/11/04 日);
79 | Zerounary 提交的 6 个 Commits, 对 APIJSON 做出了 1,104 增加和 1 处删减(截止 2020/11/04 日)。
80 | 81 |
82 | APIJSON 持续招募贡献者,新增功能、修复 Bug、完善文档、修正错误、宣传推广、回答问题等,都能帮助项目及广大用户。
83 | APIJSON 已开发近 6 年,在此感谢所有开发者对于 APIJSON 的喜欢和支持,希望你能够成为 APIJSON 的核心贡献者,
84 | 加入 APIJSON ,共同打造一个更棒的零代码、全功能、强安全 ORM 库,造福更多前后端开发者!🍾🎉 85 | 86 | ### 为什么一定要贡献代码? 87 | APIJSON 作为腾讯开源的知名热门项目,贡献代码除了可以给简历加亮点、为面试加分,还可以避免你碰到以下麻烦:
88 | 1.你在 APIJSON 上更改的代码其他人看不到,不能帮你发现 Bug,更不可能帮你修复 Bug 甚至优化代码
89 | 2.作者和其它贡献者可能不兼容你更改的代码,导致你的项目在升级 APIJSON 版本后在功能甚至编译上出错
90 | 3.你需要自己维护你的代码,每次升级 APIJSON 版本时,你都需要下载 APIJSON 新代码再合并你自己的更改
91 | #### 所以为了让你自己的更改始终能跟上项目版本,得到他人给予的可靠且持续的维护,强烈建议 [提交 Pull Request](/CONTRIBUTING.md#pull-request) 来贡献代码。 92 | 93 | ​ 94 | 95 | ## Pull Request 96 | 97 | 我们除了希望听到您的反馈和建议外,我们也希望您接受代码形式的直接帮助,对我们的 GitHub 发出 Pull Request 请求。 98 | 99 | ### 如果是小改文档或代码 100 | 101 | 直接点文件右上角的编辑图标按钮
102 | ![image](https://user-images.githubusercontent.com/5738175/130585672-8bd49ae5-2978-4ad6-a7a6-de0a0c2d0b68.png) 103 | 104 |
105 | 106 | 然后底部简要输入修改说明,点击 Commit Change 按钮
107 | ![image](https://user-images.githubusercontent.com/5738175/130586073-4a6aea74-3c88-4cd9-9c93-ffaba1270ab8.png) 108 | 109 | 110 | ### 如果有比较大的改动 111 | 112 | 以下是具体步骤:(如果使用本步骤,GitHub 可能不会把贡献者添加到 Contributors 中,推荐用以下 [详细的图文步骤](https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md#%E8%AF%A6%E7%BB%86%E7%9A%84%E5%9B%BE%E6%96%87%E6%AD%A5%E9%AA%A4%E5%8F%AF%E5%8F%82%E8%80%83%E4%BB%A5%E4%B8%8B%E4%BB%BB%E6%84%8F%E4%B8%80%E7%AF%87)) 113 | 114 | #### Fork 仓库 115 | 116 | 点击 `Fork` 按钮,将需要参与的项目仓库 Fork 到自己的 Github 中。 117 | 118 | #### Clone 已 Fork 项目 119 | 120 | 在自己的 Github 中,找到 Fork 下来的项目,git clone 到本地。 121 | 122 | ```bash 123 | $ git clone git@github.com:/APIJSON.git 124 | ``` 125 | 126 | #### 添加 APIJSON 仓库 127 | 128 | 将 Fork 源仓库连接到本地仓库: 129 | 130 | ```bash 131 | $ git remote add 132 | # 例如: 133 | $ git remote add APIJSON git@github.com:Tencent/APIJSON.git 134 | ``` 135 | 136 | #### 保持与 APIJSON 仓库的同步 137 | 138 | 直接在 fork Repo 的首页点 Contribute > Open pull request 139 | 140 | ![image](https://user-images.githubusercontent.com/5738175/131776033-74caf279-ebbf-45f1-a9c1-beff937a87fb.png) 141 | 142 | 或者 143 | ```bash 144 | $ git pull --rebase 145 | # 等同于以下两条命令 146 | $ git fetch 147 | $ git rebase / 148 | ``` 149 | 150 | #### Commit 信息提交 151 | 152 | Commit 信息请遵循 [Commit 消息约定](./CONTRIBUTING_COMMIT.md),以便可以自动生成 `CHANGELOG` 。具体格式请参考 Commit 文档规范。 153 | 154 |

155 | 156 | #### 详细的图文步骤可参考以下任意一篇 157 | GitHub - 对项目做出贡献
158 | https://www.jianshu.com/p/00cf29d2d66c 159 |

160 | 如何在 Github 上给别人的项目贡献代码
161 | https://git-scm.com/book/zh/v2/GitHub-%E5%AF%B9%E9%A1%B9%E7%9B%AE%E5%81%9A%E5%87%BA%E8%B4%A1%E7%8C%AE 162 | 163 | 164 | ​ 165 | 166 | ## Issue 提交 167 | 168 | #### 对于贡献者 169 | 170 | 在提 Issue 前请确保满足一下条件: 171 | 172 | - 必须是一个 Bug 或者功能新增。 173 | - 必须是 APIJSON 相关问题。 174 | - 已经在 Issue 中搜索过,并且没有找到相似的 Issue 或者解决方案。 175 | - 完善下面模板中的信息 176 | 177 | 如果已经满足以上条件,我们提供了 Issue 的标准模版,请按照模板填写。 178 | -------------------------------------------------------------------------------- /CONTRIBUTING_COMMIT.md: -------------------------------------------------------------------------------- 1 | # Commit 规范 2 | 3 | 在对项目作出更改后,我们需要生成 Commit 来记录自己的更改。以下是参照 Angular 对 Commit 格式的规范: 4 | 5 | ## (1) 格式 6 | 7 | 提交信息包括三个部分:`Header`,`Body` 和 `Footer`。 8 | 9 | ``` 10 |
11 | 12 | 13 | 14 |