├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── pom.xml └── src ├── main └── java │ └── com │ └── sangupta │ └── gather │ ├── Gather.java │ ├── GatherAggregator.java │ ├── GatherCriteria.java │ ├── GatherExecutor.java │ ├── GatherNumericComparison.java │ ├── GatherOperation.java │ ├── GatherReflect.java │ ├── GatherSiblingJoin.java │ └── GatherUtils.java └── test └── java └── com └── sangupta └── gather ├── TestGather.java ├── TestGatherAggregator.java ├── TestGatherExecutor.java ├── TestGatherPerformance.java ├── TestGatherProfiling.java ├── TestGatherReflect.java └── TestGatherUtils.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Java noise 2 | *.class 3 | 4 | # SVN directories 5 | .svn 6 | 7 | # OSX noise 8 | .DS_Store 9 | *.pbxuser 10 | profile 11 | 12 | # Package Files # 13 | *.jar 14 | *.war 15 | *.ear 16 | 17 | # Windows noise 18 | desktop.ini 19 | 20 | # Eclipse/Flash Builder noise 21 | .actionScriptProperties 22 | .flexProperties 23 | .project 24 | .classpath 25 | bin/* 26 | bin-debug/* 27 | report/* 28 | bin-test/* 29 | docs/* 30 | .flexLibProperties 31 | 32 | # Maven noise 33 | target/* 34 | 35 | # Project specific 36 | */.settings/* 37 | */target/* 38 | */.gitignore 39 | .settings/* 40 | /target 41 | java.hprof*.txt 42 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | sudo: false 4 | 5 | cache: 6 | directories: 7 | - $HOME/.m2 8 | 9 | matrix: 10 | include: 11 | - os: linux 12 | dist: precise 13 | jdk: oraclejdk7 14 | - os: linux 15 | dist: trusty 16 | jdk: oraclejdk8 17 | - os: linux 18 | dist: trusty 19 | jdk: oraclejdk9 20 | 21 | addons: 22 | sonarcloud: 23 | organization: "sangupta-github" # the key of the org you chose at step #3 24 | token: 25 | secure: "EavjxKCEMJS5bjgk60juMS6bG8cF30niSHBavYEFqMzX1xraWMrIvNfdZrNafMFMoA7ltuL2Y3g5pTTEyw5m+nzwxscL2C3T6pQFnm9fWbObMl9YMVT9KrEar2PKY3bx5t7ITgU4Xsy1XA0H5jmMsRyu5BSSKXNcjgxjK3Bh+H4=" 26 | 27 | after_success: 28 | - mvn clean test jacoco:report coveralls:report 29 | 30 | # script: 31 | # # other script steps might be done before running the actual analysis 32 | # - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar 33 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gather 2 | 3 | [![Build Status](https://img.shields.io/travis/sangupta/gather.svg)](https://travis-ci.org/sangupta/gather) 4 | [![Coverage Status](https://img.shields.io/coveralls/sangupta/gather.svg)](https://coveralls.io/github/sangupta/gather?branch=master) 5 | [![License](https://img.shields.io/github/license/sangupta/gather.svg)](https://opensource.org/licenses/Apache-2.0) 6 | [![Maven Central](https://img.shields.io/maven-central/v/com.sangupta/gather.svg)](https://maven-badges.herokuapp.com/maven-central/com.sangupta/gather) 7 | 8 | `Gather` is an ultra-lightweight, 37KB, no dependencies library to fire SQL like queries on Java collections 9 | and arrays. The data is not inserted into any in-memory database, nor any index is created. The query is matched 10 | against all the objects (could be different types as well) against the provided query. Useful to run ad-hoc 11 | queries and aggregation functions, say on XML/JSON/CSV and more. 12 | 13 | The library is tested on the following JDK versions: 14 | 15 | * Oracle JDK 9 16 | * Oracle JDK 8 17 | * Oracle JDK 7 18 | 19 | ## Table of Contents 20 | 21 | * [Usecases](#usecases) 22 | * [Usage Examples](#usage-examples) 23 | * [Composed Objects and Keys](#composed-objects-and-keys) 24 | * [Features](#features) 25 | * [Roadmap](#roadmap) 26 | * [Clause chaining and Evaluation](#clause-chaining-and-evaluation) 27 | * [Performance](#performance) 28 | * [Downloads](#downloads) 29 | * [Release Notes](#release-notes) 30 | * [Versioning](#versioning) 31 | * [License](#license) 32 | 33 | ## Usecases 34 | 35 | The library is useful in the following scenarios: 36 | 37 | * Run ad-hoc queries during development to debug data-sets and tweak DB queries 38 | * Run ad-hoc queries on production data via some admin interface 39 | * Query on objects of different types in one-shot, say `List` than `List` 40 | * Works with JDK 9, 8, 7 and legacy code 41 | 42 | 43 | ## Usage Examples 44 | 45 | ```java 46 | List employees = this.employeeService.getAllEmployeesFromDatabase(); 47 | 48 | // prepare a query 49 | Gather query = Gather.where("age").greaterThan(50).and("status").is("active"); 50 | 51 | // fire query 52 | List filtered = query.find(employees); 53 | 54 | // reuse the query for another collection 55 | List managers = this.employeeService.getAllManagersFromDatabase(); 56 | 57 | List filteredManagers = query.find(managers); 58 | 59 | // null check operations 60 | query = Gather.where("name").isNull(); 61 | query = Gather.where("name").isNotNull(); 62 | 63 | // not operator 64 | query = Gather.where("name").not().is("sandeep"); 65 | 66 | // find instances that have a property 67 | // one of the two ways can be employed 68 | gather = Gather.where("name").existsProperty(); 69 | gather = Gather.hasProperty("name"); 70 | 71 | // query if an attribute which is a collection or an array contains a given value 72 | // converting between various primitive value types is supported 73 | gather = Gather.where("someFloatArray").has(new Double(123)); 74 | 75 | // run over collections as well 76 | gather = Gather.where("collection").has(objectInstance); 77 | 78 | // find a single instance 79 | query.findOne(employees); 80 | 81 | // find limited instances 82 | query.find(employees, 5); 83 | 84 | // find 5 instances, but skip the first 10 instances 85 | query.find(employees, 5, 10); 86 | 87 | // count the number of results rather than accumulating them 88 | // this is much faster and memory efficient 89 | int numResults = query.count(employees); 90 | ``` 91 | 92 | ## Composed Objects and Keys 93 | 94 | `Gather` supports composed objects and keys in the `where` clause based on them. For example: the 95 | following query will search all objects in the collection/array called `children` which have an `age` 96 | attribute and its value is less than `40`. 97 | 98 | ```java 99 | Gather query = Gather.where("children.age").lessThan(10); 100 | 101 | query.find(employees); 102 | 103 | public class Employee { 104 | 105 | public List children; 106 | 107 | } 108 | 109 | public class Child { 110 | 111 | public int age; 112 | 113 | } 114 | ``` 115 | 116 | ## Features 117 | 118 | * Gathering operations 119 | * `find` - find all matching objects, with options to skip elements and/or limit number of matches 120 | * `findOne` - find the first matching object 121 | * `count` - count the total number of matching objects 122 | * `aggregate` - run a custom aggregator on a collection/array for a given field 123 | * Supported operations 124 | * `is` - equals match 125 | * `isIgnoreCase` - equals match ignoring case on strings 126 | * `isNull` - check if a property is null 127 | * `isNotNull` - check if a property is not null 128 | * `like` - wildcard match on strings 129 | * `regex` - Java regular expression match on strings 130 | * `has` - check if value is contained in a collection or an array 131 | * `hasAll` - check if all values are contained in a collection or an array 132 | * `hasAny` - check if any of the value are present in a collection or an array 133 | * `not` - negate the match expression 134 | * `existsProperty` - check if property exists on object 135 | * `notExistsProperty` - check if property does not exists on object 136 | * `lessThan` - if a value is less than property value 137 | * `lessThanOrEquals` - if a value is equal or less than property value 138 | * `greaterThan` - if a value is greater than property value 139 | * `greaterThanOrEquals` - if a value is equal or greater than property value 140 | * Boolean operations supported 141 | * `and` - Boolean AND between two clauses 142 | * `or` - Boolean OR between two clauses 143 | * Aggregation operations 144 | * `averageAsLong` - find average value of a field which has no decimal part 145 | * `averageAsDouble` - find average value of a field which has a decimal part 146 | * `minAsLong` - find minimum value of a field which has no decimal part 147 | * `minAsDouble` - find minimum value of a field which has a decimal part 148 | * `maxAsLong` - find maximum value of a field which has no decimal part 149 | * `maxAsDouble` - find maximum value of a field which has a decimal part 150 | * `sumAsLong` - find total sum of value of a field which has no decimal part 151 | * `sumAsDouble` - find total sum of value of a field which has a decimal part 152 | * `unique` - find the number of unique objects from the result set 153 | * `count` - count objects in a collection/array which have a given field 154 | 155 | ## RoadMap 156 | 157 | * Support for `uniqueAs("someKey", String.class)` to return `Set` than `Set` 158 | * Support for `groupBy("someKey")` to return a `Map>` 159 | 160 | ## Clause chaining and Evaluation 161 | 162 | When more than one clause is added to the query and Boolean operations like `AND` or `OR` are used 163 | to connect them, the evaluation happens from left to right. The first clause is evaluated first and 164 | then the result is boolean `AND`/`OR` with the result of next clause depending on connecting operation 165 | type. 166 | 167 | For example: 168 | 169 | ```java 170 | Gather.where("name").like("sandeep*").and("age").lessThan(50).or("status").is("active"); 171 | ``` 172 | 173 | The evaluation happens in the order: 174 | 175 | ```java 176 | boolean first = evaluate("name like 'sandeep*'"); 177 | boolean second = evaluate("age < 50"); 178 | boolean third = evaluate("status == 'active'"); 179 | return first & second | third; 180 | ``` 181 | 182 | ## Performance 183 | 184 | Performance numbers and percentage changes (compared to previous run). Values are operations-per-second. 185 | An operation is a query fired over a million objects created randomly for a `LIKE` clause and a `GREATER THAN` 186 | clause. 187 | 188 | | Version | Date Run | `LIKE` clause | %age change | Numeric `GREATER THAN` clause | %age change | 189 | |----------|--------------|---------------|-------------|-------------------------------|-------------| 190 | | 1.0.0 | 10 Jan 2018 | 3.240 | n/a | 3.215 | n/a | 191 | | 1.2.0 | 10 Jan 2018 | 4.160 | +28 | 5.792 | +80 | 192 | | Snapshot | 10 Jan 2018 | 5.322 | +28 | 5.735 | +0 | 193 | 194 | Test Machine specs: 195 | 196 | ``` 197 | Macbook Pro (2017) 198 | 2.9GHz Intel i7 199 | 16GB RAM 200 | OS X 10.12.6 201 | Oracle JDK 1.8.0_131 202 | Tests run from inside Eclipse Oxygen.2 (4.7.2) release 203 | ``` 204 | 205 | JMH options used were: 206 | 207 | ``` 208 | # JMH version: 1.19 209 | # VM version: JDK 1.8.0_131, VM 25.131-b11 210 | # VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/bin/java 211 | # VM options: -Dfile.encoding=UTF-8 212 | # Warmup: 5 iterations, 1 s each 213 | # Measurement: 20 iterations, 1 s each 214 | # Timeout: 10 min per iteration 215 | # Forks: 5 216 | # Threads: 1 thread, will synchronize iterations 217 | # Benchmark mode: Throughput, ops/time 218 | ``` 219 | 220 | **Caveat:** Your mileage may vary. 221 | 222 | ## Downloads 223 | 224 | The latest stable release of the library can be downloaded via the Maven Central using the following coordinates: 225 | 226 | ```xml 227 | 228 | com.sangupta 229 | gather 230 | 1.2.0 231 | 232 | ``` 233 | 234 | The current/latest development snapshot `JAR` can be obtained using `JitPack.io` as: 235 | 236 | Add the following repository to Maven, 237 | 238 | ```xml 239 | 240 | jitpack.io 241 | https://jitpack.io 242 | 243 | ``` 244 | 245 | Then add the dependency as, 246 | 247 | ```xml 248 | 249 | com.github.sangupta 250 | gather 251 | -SNAPSHOT 252 | 253 | ``` 254 | 255 | ## Release Notes 256 | 257 | **Snapshot** 258 | 259 | * Improve performance of `wildcard` matches 260 | 261 | **1.2.0 (21 Dec 2017)** 262 | 263 | * Query on `object arrays` than just `Collections` 264 | * Added caching to improve performance 265 | * Updated for newer OSSRH release guidelines 266 | * Updated `javadocs` and copyright headers 267 | 268 | **1.0.0 (09 Jun 2017)** 269 | 270 | * First stable release 271 | 272 | 273 | ## Versioning 274 | 275 | For transparency and insight into our release cycle, and for striving to maintain 276 | backward compatibility, `gather` will be maintained under the Semantic 277 | Versioning guidelines as much as possible. 278 | 279 | Releases will be numbered with the follow format: 280 | 281 | ``` 282 | .. 283 | ``` 284 | 285 | And constructed with the following guidelines: 286 | 287 | * Breaking backward compatibility bumps the major 288 | * New additions without breaking backward compatibility bumps the minor 289 | * Bug fixes and misc changes bump the patch 290 | 291 | For more information on SemVer, please visit http://semver.org/. 292 | 293 | ## License 294 | 295 | ``` 296 | gather: SQL queries for Java collections 297 | Copyright (c) 2017-2018, Sandeep Gupta 298 | 299 | https://sangupta.com/projects/gather 300 | 301 | Licensed under the Apache License, Version 2.0 (the "License"); 302 | you may not use this file except in compliance with the License. 303 | You may obtain a copy of the License at 304 | 305 | http://www.apache.org/licenses/LICENSE-2.0 306 | 307 | Unless required by applicable law or agreed to in writing, software 308 | distributed under the License is distributed on an "AS IS" BASIS, 309 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 310 | See the License for the specific language governing permissions and 311 | limitations under the License. 312 | ``` 313 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.sangupta 6 | gather 7 | 1.2.1-SNAPSHOT 8 | jar 9 | 10 | gather 11 | SQL queries for Java collections 12 | https://sangupta.com/projects/gather 13 | 2017 14 | 15 | 16 | 17 | The Apache Software License, Version 2.0 18 | http://www.apache.org/licenses/LICENSE-2.0.txt 19 | 20 | 21 | 22 | 23 | scm:git:ssh://git@github.com/sangupta/gather.git 24 | scm:git:ssh://git@github.com/sangupta/gather.git 25 | https://github.com/sangupta/gather 26 | HEAD 27 | 28 | 29 | 30 | 31 | sangupta 32 | Sandeep Gupta 33 | sandy.pec@gmail.com 34 | https://sangupta.com 35 | 36 | 37 | 38 | 39 | UTF-8 40 | UTF-8 41 | 42 | yyyyMMddHHmm 43 | ${maven.build.timestamp} 44 | 45 | 46 | 47 | 48 | 49 | ossrh 50 | https://oss.sonatype.org/content/repositories/snapshots 51 | 52 | 53 | ossrh 54 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 55 | 56 | 57 | 58 | 59 | 60 | junit 61 | junit 62 | 4.13.1 63 | test 64 | 65 | 66 | 67 | 68 | org.openjdk.jmh 69 | jmh-core 70 | 1.19 71 | test 72 | 73 | 74 | org.openjdk.jmh 75 | jmh-generator-annprocess 76 | 1.19 77 | test 78 | 79 | 80 | 81 | 82 | 83 | 84 | org.apache.maven.plugins 85 | maven-compiler-plugin 86 | 3.7.0 87 | 88 | 1.7 89 | 1.7 90 | 91 | 92 | 93 | 94 | 95 | org.jacoco 96 | jacoco-maven-plugin 97 | 0.8.0 98 | 99 | 100 | prepare-agent 101 | 102 | prepare-agent 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | org.eluder.coveralls 111 | coveralls-maven-plugin 112 | 4.3.0 113 | 114 | 115 | 116 | 117 | 118 | 119 | performance 120 | 121 | 122 | 123 | 124 | org.codehaus.mojo 125 | exec-maven-plugin 126 | 1.6.0 127 | 128 | 129 | run-benchmarks 130 | integration-test 131 | 132 | exec 133 | 134 | 135 | test 136 | ${java.home}/bin/java 137 | 138 | -classpath 139 | 140 | org.openjdk.jmh.Main 141 | .* 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | release 152 | 153 | 154 | 155 | 156 | org.apache.maven.plugins 157 | maven-javadoc-plugin 158 | 3.0.0 159 | 160 | 161 | attach-javadocs 162 | 163 | jar 164 | 165 | 166 | 167 | 168 | false 169 | true 170 | false 171 | false 172 | true 173 | 174 | 175 | 176 | 177 | 178 | org.apache.maven.plugins 179 | maven-source-plugin 180 | 3.0.1 181 | 182 | 183 | attach-sources 184 | 185 | jar 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | org.sonatype.plugins 194 | nexus-staging-maven-plugin 195 | 1.6.8 196 | true 197 | 198 | ossrh 199 | https://oss.sonatype.org/ 200 | true 201 | 202 | 203 | 204 | 205 | 206 | org.apache.maven.plugins 207 | maven-gpg-plugin 208 | 1.6 209 | 210 | 211 | sign-artifacts 212 | verify 213 | 214 | sign 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | org.apache.maven.plugins 223 | maven-release-plugin 224 | 2.5.3 225 | 226 | true 227 | false 228 | release 229 | deploy 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | -------------------------------------------------------------------------------- /src/main/java/com/sangupta/gather/Gather.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | import java.util.ArrayList; 25 | import java.util.Collection; 26 | import java.util.List; 27 | import java.util.Set; 28 | import java.util.regex.Pattern; 29 | 30 | /** 31 | * Gather is the main query class that a callee deals with. Once the query is 32 | * built up they can fire it on a collection of objects. For example, 33 | * Gather query = Gather.where("name").is("sangupta").and("age").lessThan(40); 34 | * is a valid query to be fired on a collection of objects. 35 | * 36 | * @author sangupta 37 | * 38 | * @since 1.0.0 39 | */ 40 | public class Gather { 41 | 42 | /** 43 | * List of all {@link GatherCriteria} added to this query 44 | */ 45 | final List criteria = new ArrayList<>(); 46 | 47 | /** 48 | * The field name over which the query clause will fire 49 | */ 50 | private String key; 51 | 52 | /** 53 | * The default sibling join method for clauses 54 | */ 55 | private GatherSiblingJoin siblingJoin = GatherSiblingJoin.OR; 56 | 57 | /** 58 | * Is inverse (read NOT) mode on? 59 | */ 60 | private boolean inverse = false; 61 | 62 | // *************************************** 63 | // STATIC METHODS FOLLOW 64 | // *************************************** 65 | 66 | /** 67 | * Start a WHERE clause 68 | * 69 | * @param name 70 | * the name of the WHERE property 71 | * 72 | * @return this very {@link Gather} instance 73 | */ 74 | public static Gather where(String name) { 75 | return new Gather(name); 76 | } 77 | 78 | /** 79 | * Add a WHERE clause to see if the property exists 80 | * 81 | * @param name 82 | * the name of the property 83 | * 84 | * @return this very {@link Gather} instance 85 | */ 86 | public static Gather hasProperty(String name) { 87 | Gather instance = new Gather(name); 88 | instance.existsProperty(); 89 | return instance; 90 | } 91 | 92 | // *************************************** 93 | // AGGREGATION METHODS FOLLOW 94 | // *************************************** 95 | 96 | public static void aggregate(Collection collection, String key, GatherAggregator aggregator) { 97 | GatherExecutor.aggregate(collection, key, aggregator); 98 | } 99 | 100 | public static void aggregate(Object[] array, String key, GatherAggregator aggregator) { 101 | GatherExecutor.aggregate(array, key, aggregator); 102 | } 103 | 104 | /** 105 | * Find unique values for the given key from collection of objects 106 | * 107 | * @param collection 108 | * the collection of objects 109 | * 110 | * @param key 111 | * the key being looked for 112 | * 113 | * @return {@link Set} of unique objects, as Set<Object> 114 | */ 115 | public static Set unique(Collection collection, String key) { 116 | GatherAggregator.UniqueAggregator aggregator = new GatherAggregator.UniqueAggregator(); 117 | GatherExecutor.aggregate(collection, key, aggregator); 118 | 119 | return aggregator.set; 120 | } 121 | 122 | /** 123 | * Find unique values for the given key from array of objects 124 | * 125 | * @param collection 126 | * the collection of objects 127 | * 128 | * @param key 129 | * the key being looked for 130 | * 131 | * @return {@link Set} of unique objects, as Set<Object> 132 | */ 133 | public static Set unique(Object[] collection, String key) { 134 | GatherAggregator.UniqueAggregator aggregator = new GatherAggregator.UniqueAggregator(); 135 | GatherExecutor.aggregate(collection, key, aggregator); 136 | 137 | return aggregator.set; 138 | } 139 | 140 | public static Number count(Collection collection, String key) { 141 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.CountingAggregator()); 142 | } 143 | 144 | public static Number count(Object[] collection, String key) { 145 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.CountingAggregator()); 146 | } 147 | 148 | public static Number sumAsLong(Collection collection, String key) { 149 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.LongSumAggregator()); 150 | } 151 | 152 | public static Number sumAsLong(Object[] collection, String key) { 153 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.LongSumAggregator()); 154 | } 155 | 156 | public static Number sumAsDouble(Collection collection, String key) { 157 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.DoubleSumAggregator()); 158 | } 159 | 160 | public static Number sumAsDouble(Object[] collection, String key) { 161 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.DoubleSumAggregator()); 162 | } 163 | 164 | public static Number minAsLong(Collection collection, String key) { 165 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.LongMinAggregator()); 166 | } 167 | 168 | public static Number minAsLong(Object[] collection, String key) { 169 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.LongMinAggregator()); 170 | } 171 | 172 | public static Number minAsDouble(Collection collection, String key) { 173 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.DoubleMinAggregator()); 174 | } 175 | 176 | public static Number minAsDouble(Object[] collection, String key) { 177 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.DoubleMinAggregator()); 178 | } 179 | 180 | public static Number maxAsLong(Collection collection, String key) { 181 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.LongMaxAggregator()); 182 | } 183 | 184 | public static Number maxAsLong(Object[] collection, String key) { 185 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.LongMaxAggregator()); 186 | } 187 | 188 | public static Number maxAsDouble(Collection collection, String key) { 189 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.DoubleMaxAggregator()); 190 | } 191 | 192 | public static Number maxAsDouble(Object[] collection, String key) { 193 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.DoubleMaxAggregator()); 194 | } 195 | 196 | public static Number averageAsLong(Collection collection, String key) { 197 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.LongAverageAggregator()); 198 | } 199 | 200 | public static Number averageAsLong(Object[] collection, String key) { 201 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.LongAverageAggregator()); 202 | } 203 | 204 | public static Number averageAsDouble(Collection collection, String key) { 205 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.DoubleAverageAggregator()); 206 | } 207 | 208 | public static Number averageAsDouble(Object[] collection, String key) { 209 | return GatherExecutor.aggregate(collection, key, new GatherAggregator.DoubleAverageAggregator()); 210 | } 211 | 212 | // *************************************** 213 | // PUBLIC INSTANCE METHODS FOLLOW 214 | // *************************************** 215 | 216 | private Gather(String key) { 217 | this.key = key; 218 | } 219 | 220 | public Gather and(String key) { 221 | if(this.key != null) { 222 | throw new IllegalArgumentException("Add a comparison condition to previous key first"); 223 | } 224 | 225 | this.key = key; 226 | this.siblingJoin = GatherSiblingJoin.AND; 227 | this.inverse = false; 228 | return this; 229 | } 230 | 231 | public Gather not() { 232 | if(this.key == null) { 233 | throw new IllegalArgumentException("Define a key first"); 234 | } 235 | 236 | this.inverse = true; 237 | return this; 238 | } 239 | 240 | public Gather or(String key) { 241 | if(this.key != null) { 242 | throw new IllegalArgumentException("Add a comparison condition to previous key first"); 243 | } 244 | 245 | this.key = key; 246 | this.siblingJoin = GatherSiblingJoin.OR; 247 | this.inverse = false; 248 | return this; 249 | } 250 | 251 | /** 252 | * Check if the attribute value is equivalent to the given value. 253 | * 254 | * @param value 255 | * the object value to compare against 256 | * 257 | * @return this {@link Gather} instance 258 | */ 259 | public Gather is(Object value) { 260 | if(this.key == null) { 261 | throw new IllegalArgumentException("Operation needs a key to work upon"); 262 | } 263 | 264 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.Equals, value, this.siblingJoin, this.inverse)); 265 | return fluent(); 266 | } 267 | 268 | public Gather existsProperty() { 269 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.HasProperty, null, this.siblingJoin, false)); 270 | return fluent(); 271 | } 272 | 273 | public Gather notExistsProperty() { 274 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.HasProperty, null, this.siblingJoin, true)); 275 | return fluent(); 276 | } 277 | 278 | public Gather has(Object value) { 279 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.CollectionHasValue, value, this.siblingJoin, this.inverse)); 280 | return fluent(); 281 | } 282 | 283 | public Gather hasAll(Collection value) { 284 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.CollectionHasAllValues, value, this.siblingJoin, this.inverse)); 285 | return fluent(); 286 | } 287 | 288 | public Gather hasAll(Object[] value) { 289 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.CollectionHasAllValues, value, this.siblingJoin, this.inverse)); 290 | return fluent(); 291 | } 292 | 293 | public Gather hasAny(Collection value) { 294 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.CollectionHasAnyValue, value, this.siblingJoin, this.inverse)); 295 | return fluent(); 296 | } 297 | 298 | public Gather hasAny(Object[] value) { 299 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.CollectionHasAnyValue, value, this.siblingJoin, this.inverse)); 300 | return fluent(); 301 | } 302 | 303 | /** 304 | * Check if the attribute value is null. 305 | * 306 | * @return this {@link Gather} instance 307 | */ 308 | public Gather isNull() { 309 | if(this.key == null) { 310 | throw new IllegalArgumentException("Operation needs a key to work upon"); 311 | } 312 | 313 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.IsNull, null, this.siblingJoin, this.inverse)); 314 | return fluent(); 315 | } 316 | 317 | /** 318 | * Check if the attribute value is null. 319 | * 320 | * @return this {@link Gather} instance 321 | */ 322 | public Gather isNotNull() { 323 | if(this.key == null) { 324 | throw new IllegalArgumentException("Operation needs a key to work upon"); 325 | } 326 | 327 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.IsNull, null, this.siblingJoin, true)); 328 | return fluent(); 329 | } 330 | 331 | public Gather in(Collection collection) { 332 | if(this.key == null) { 333 | throw new IllegalArgumentException("Operation needs a key to work upon"); 334 | } 335 | 336 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.In, collection, this.siblingJoin, this.inverse)); 337 | return fluent(); 338 | } 339 | 340 | public Gather in(Object[] array) { 341 | if(this.key == null) { 342 | throw new IllegalArgumentException("Operation needs a key to work upon"); 343 | } 344 | 345 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.In, array, this.siblingJoin, this.inverse)); 346 | return fluent(); 347 | } 348 | 349 | /** 350 | * Check if the attribute value equals to the given value ignoring case. 351 | * 352 | * @param value 353 | * {@link String} value to compare against 354 | * 355 | * @return this {@link Gather} instance 356 | */ 357 | public Gather isIgnoreCase(String value) { 358 | if(this.key == null) { 359 | throw new IllegalArgumentException("Operation needs a key to work upon"); 360 | } 361 | 362 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.EqualsIgnoreCase, value, this.siblingJoin, this.inverse)); 363 | return fluent(); 364 | } 365 | 366 | /** 367 | * Check if the attribute value matches the given value as a wildcard 368 | * pattern. 369 | * 370 | * @param pattern 371 | * wildcard pattern to compare against 372 | * 373 | * @return this {@link Gather} instance 374 | */ 375 | public Gather like(String pattern) { 376 | if(this.key == null) { 377 | throw new IllegalArgumentException("Operation needs a key to work upon"); 378 | } 379 | 380 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.WildcardMatch, pattern, this.siblingJoin, this.inverse)); 381 | return fluent(); 382 | } 383 | 384 | /** 385 | * Check if the attribute value matches the given value as a 386 | * regular-expression match. 387 | * 388 | * @param pattern 389 | * regex pattern to compare against 390 | * 391 | * @return this {@link Gather} instance 392 | */ 393 | public Gather regex(String pattern) { 394 | if(this.key == null) { 395 | throw new IllegalArgumentException("Operation needs a key to work upon"); 396 | } 397 | 398 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.RegexMatch, pattern, this.siblingJoin, this.inverse)); 399 | return fluent(); 400 | } 401 | 402 | /** 403 | * Check if the attribute value matches the given value as a 404 | * regular-expression match. 405 | * 406 | * @param pattern 407 | * regex {@link Pattern} to compare against 408 | * 409 | * @return this {@link Gather} instance 410 | */ 411 | public Gather regex(Pattern pattern) { 412 | if(this.key == null) { 413 | throw new IllegalArgumentException("Operation needs a key to work upon"); 414 | } 415 | 416 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.RegexMatch, pattern, this.siblingJoin, this.inverse)); 417 | return fluent(); 418 | } 419 | 420 | public Gather greaterThan(Object value) { 421 | if(this.key == null) { 422 | throw new IllegalArgumentException("Operation needs a key to work upon"); 423 | } 424 | 425 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.GreaterThan, value, this.siblingJoin, this.inverse)); 426 | return fluent(); 427 | } 428 | 429 | public Gather greaterThanOrEquals(Object value) { 430 | if(this.key == null) { 431 | throw new IllegalArgumentException("Operation needs a key to work upon"); 432 | } 433 | 434 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.GreaterThanOrEquals, value, this.siblingJoin, this.inverse)); 435 | return fluent(); 436 | } 437 | 438 | public Gather lessThan(Object value) { 439 | if(this.key == null) { 440 | throw new IllegalArgumentException("Operation needs a key to work upon"); 441 | } 442 | 443 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.LessThan, value, this.siblingJoin, this.inverse)); 444 | return fluent(); 445 | } 446 | 447 | public Gather lessThanOrEquals(Object value) { 448 | if(this.key == null) { 449 | throw new IllegalArgumentException("Operation needs a key to work upon"); 450 | } 451 | 452 | this.criteria.add(new GatherCriteria(this.key, GatherOperation.LessThanOrEquals, value, this.siblingJoin, this.inverse)); 453 | return fluent(); 454 | } 455 | 456 | /** 457 | * Count the number of objects that match the given criteria in the given 458 | * collection. 459 | * 460 | * @param collection 461 | * the {@link Collection} to count items in 462 | * 463 | * @return the number of items that matched the criteria 464 | */ 465 | public int count(Collection collection) { 466 | if(collection == null) { 467 | return 0; 468 | } 469 | 470 | if(collection.isEmpty()) { 471 | return 0; 472 | } 473 | 474 | return GatherExecutor.count(collection, this); 475 | } 476 | 477 | public int count(Object[] array) { 478 | if(array == null) { 479 | return 0; 480 | } 481 | 482 | if(array.length == 0) { 483 | return 0; 484 | } 485 | 486 | return GatherExecutor.count(array, this); 487 | } 488 | 489 | /** 490 | * Execute the query over the given collection of objects. 491 | * 492 | * @param collection 493 | * the collection to run {@link Gather} query against 494 | * 495 | * @return the results, if any, found after running the query 496 | */ 497 | public List find(Collection collection) { 498 | return GatherExecutor.getResults(collection, this, 0, 0); 499 | } 500 | 501 | public List find(Collection collection, int numResults) { 502 | return GatherExecutor.getResults(collection, this, numResults, 0); 503 | } 504 | 505 | public List find(Collection collection, int numResults, int skipCount) { 506 | return GatherExecutor.getResults(collection, this, numResults, skipCount); 507 | } 508 | 509 | public T findOne(Collection collection) { 510 | return findOne(collection, 0); 511 | } 512 | 513 | public T findOne(Collection collection, int skipCount) { 514 | List results = GatherExecutor.getResults(collection, this, 1, skipCount); 515 | if(results == null || results.isEmpty()) { 516 | return null; 517 | } 518 | 519 | return results.get(0); 520 | } 521 | 522 | // *************************************** 523 | // INTERNAL INSTANCE METHODS FOLLOW 524 | // *************************************** 525 | 526 | Gather fluent() { 527 | this.key = null; 528 | this.inverse = false; 529 | return this; 530 | } 531 | 532 | } 533 | -------------------------------------------------------------------------------- /src/main/java/com/sangupta/gather/GatherAggregator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | import java.util.HashSet; 25 | import java.util.Set; 26 | 27 | /** 28 | * 29 | * @author sangupta 30 | * 31 | * @since 1.0.0 32 | */ 33 | public interface GatherAggregator { 34 | 35 | public void aggregate(int index, Object value); 36 | 37 | public Number getResult(int counted); 38 | 39 | // *************************************** 40 | // DEFAULT IMPLEMENTATIONS FOLLOW 41 | // *************************************** 42 | 43 | static class UniqueAggregator implements GatherAggregator { 44 | 45 | final Set set = new HashSet<>(); 46 | 47 | @Override 48 | public void aggregate(int index, Object value) { 49 | if(value == null) { 50 | return; 51 | } 52 | 53 | this.set.add(value); 54 | } 55 | 56 | @Override 57 | public Number getResult(int counted) { 58 | return this.set.size(); 59 | } 60 | 61 | public Set getUniqueSet() { 62 | return this.set; 63 | } 64 | 65 | } 66 | 67 | static class CountingAggregator implements GatherAggregator { 68 | 69 | int count = 0; 70 | 71 | @Override 72 | public void aggregate(int index, Object value) { 73 | count++; 74 | } 75 | 76 | @Override 77 | public Number getResult(int counted) { 78 | return this.count; 79 | } 80 | } 81 | 82 | static class DoubleMinAggregator implements GatherAggregator { 83 | 84 | double result = Double.MAX_VALUE; 85 | 86 | @Override 87 | public void aggregate(int index, Object value) { 88 | double fieldValue; 89 | 90 | if(value instanceof Number) { 91 | fieldValue = ((Number) value).doubleValue(); 92 | } else { 93 | throw new IllegalArgumentException("Field type is not numeric"); 94 | } 95 | 96 | if(result > fieldValue) { 97 | result = fieldValue; 98 | } 99 | } 100 | 101 | @Override 102 | public Number getResult(int counted) { 103 | return this.result; 104 | } 105 | } 106 | 107 | static class DoubleSumAggregator implements GatherAggregator { 108 | 109 | double result = 0; 110 | 111 | @Override 112 | public void aggregate(int index, Object value) { 113 | double fieldValue; 114 | 115 | if(value instanceof Number) { 116 | fieldValue = ((Number) value).doubleValue(); 117 | } else { 118 | throw new IllegalArgumentException("Field type is not numeric"); 119 | } 120 | 121 | result += fieldValue; 122 | } 123 | 124 | @Override 125 | public Number getResult(int counted) { 126 | return this.result; 127 | } 128 | } 129 | 130 | static class DoubleAverageAggregator implements GatherAggregator { 131 | 132 | double result = 0; 133 | 134 | int count = 0; 135 | 136 | @Override 137 | public void aggregate(int index, Object value) { 138 | double fieldValue; 139 | 140 | if(value instanceof Number) { 141 | fieldValue = ((Number) value).doubleValue(); 142 | } else { 143 | throw new IllegalArgumentException("Field type is not numeric"); 144 | } 145 | 146 | result += fieldValue; 147 | count++; 148 | } 149 | 150 | @Override 151 | public Number getResult(int counted) { 152 | if(this.count == 0) { 153 | return 0d; 154 | } 155 | 156 | return (double) this.result / (double) this.count; 157 | } 158 | } 159 | 160 | static class DoubleMaxAggregator implements GatherAggregator { 161 | 162 | double result = Double.MIN_VALUE; 163 | 164 | @Override 165 | public void aggregate(int index, Object value) { 166 | double fieldValue; 167 | 168 | if(value instanceof Number) { 169 | fieldValue = ((Number) value).doubleValue(); 170 | } else { 171 | throw new IllegalArgumentException("Field type is not numeric"); 172 | } 173 | 174 | if(result < fieldValue) { 175 | result = fieldValue; 176 | } 177 | } 178 | 179 | @Override 180 | public Number getResult(int counted) { 181 | return this.result; 182 | } 183 | } 184 | 185 | static class LongMinAggregator implements GatherAggregator { 186 | 187 | long result = Long.MAX_VALUE; 188 | 189 | @Override 190 | public void aggregate(int index, Object value) { 191 | long fieldValue; 192 | 193 | if(value instanceof Number) { 194 | fieldValue = ((Number) value).longValue(); 195 | } else { 196 | throw new IllegalArgumentException("Field type is not numeric"); 197 | } 198 | 199 | if(result > fieldValue) { 200 | result = fieldValue; 201 | } 202 | } 203 | 204 | @Override 205 | public Number getResult(int counted) { 206 | return this.result; 207 | } 208 | } 209 | 210 | static class LongMaxAggregator implements GatherAggregator { 211 | 212 | long result = Long.MIN_VALUE; 213 | 214 | @Override 215 | public void aggregate(int index, Object value) { 216 | long fieldValue; 217 | 218 | if(value instanceof Number) { 219 | fieldValue = ((Number) value).longValue(); 220 | } else { 221 | throw new IllegalArgumentException("Field type is not numeric"); 222 | } 223 | 224 | if(result < fieldValue) { 225 | result = fieldValue; 226 | } 227 | } 228 | 229 | @Override 230 | public Number getResult(int counted) { 231 | return this.result; 232 | } 233 | } 234 | 235 | static class LongSumAggregator implements GatherAggregator { 236 | 237 | long result = 0; 238 | 239 | @Override 240 | public void aggregate(int index, Object value) { 241 | long fieldValue; 242 | 243 | if(value instanceof Number) { 244 | fieldValue = ((Number) value).longValue(); 245 | } else { 246 | throw new IllegalArgumentException("Field type is not numeric"); 247 | } 248 | 249 | result += fieldValue; 250 | } 251 | 252 | @Override 253 | public Number getResult(int counted) { 254 | return this.result; 255 | } 256 | } 257 | 258 | static class LongAverageAggregator implements GatherAggregator { 259 | 260 | long result = 0; 261 | 262 | int count = 0; 263 | 264 | @Override 265 | public void aggregate(int index, Object value) { 266 | long fieldValue; 267 | 268 | if(value instanceof Number) { 269 | fieldValue = ((Number) value).longValue(); 270 | } else { 271 | throw new IllegalArgumentException("Field type is not numeric"); 272 | } 273 | 274 | result += fieldValue; 275 | count++; 276 | } 277 | 278 | /** 279 | * @param counted the parameter value is not used and ignored 280 | */ 281 | @Override 282 | public Number getResult(int counted) { 283 | if(this.count == 0) { 284 | return 0d; 285 | } 286 | 287 | return this.result / this.count; 288 | } 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /src/main/java/com/sangupta/gather/GatherCriteria.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | /** 25 | * A single criteria in a {@link Gather} query. 26 | * 27 | * @author sangupta 28 | * 29 | * @since 1.0.0 30 | */ 31 | class GatherCriteria { 32 | 33 | public final String key; 34 | 35 | public final Object value; 36 | 37 | public final GatherOperation operation; 38 | 39 | public final GatherSiblingJoin join; 40 | 41 | public final boolean inverse; 42 | 43 | public GatherCriteria(String key, GatherOperation operation, Object value, GatherSiblingJoin siblingJoin, boolean inverse) { 44 | this.key = key; 45 | this.operation = operation; 46 | this.value = value; 47 | this.join = siblingJoin; 48 | this.inverse = inverse; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/sangupta/gather/GatherExecutor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | import java.lang.reflect.Field; 25 | import java.util.ArrayList; 26 | import java.util.Collection; 27 | import java.util.List; 28 | import java.util.regex.Pattern; 29 | 30 | import com.sangupta.gather.GatherReflect.FieldAndInstance; 31 | 32 | /** 33 | * The query executor that takes a {@link Gather} query and fires it against a given 34 | * collection of objects. 35 | * 36 | * @author sangupta 37 | * 38 | * @since 1.0.0 39 | */ 40 | abstract class GatherExecutor { 41 | 42 | /** 43 | * Run the given aggregator on the collection over the given key. 44 | * 45 | * @param collection 46 | * Object collection to run aggregation on 47 | * 48 | * @param key 49 | * the key to fire aggregation on 50 | * 51 | * @param aggregator 52 | * the {@link GatherAggregator} to use 53 | * 54 | * @return the result of the {@link GatherAggregator} as a {@link Number} 55 | */ 56 | static Number aggregate(Collection collection, String key, GatherAggregator aggregator) { 57 | if(collection == null) { 58 | return null; 59 | } 60 | 61 | if(key == null) { 62 | return null; 63 | } 64 | 65 | if(aggregator == null) { 66 | return null; 67 | } 68 | 69 | if(collection.isEmpty()) { 70 | return null; 71 | } 72 | 73 | int found = 0; 74 | for(T item : collection) { 75 | found = aggregateOnItem(item, key, aggregator, found); 76 | } 77 | 78 | return aggregator.getResult(found); 79 | } 80 | 81 | /** 82 | * Run the given aggregator on the collection as array over the given key. 83 | * 84 | * @param array 85 | * Object collection as array to run aggregation on 86 | * 87 | * @param key 88 | * the key to fire aggregation on 89 | * 90 | * @param aggregator 91 | * the {@link GatherAggregator} to use 92 | * 93 | * @return the result of the {@link GatherAggregator} as a {@link Number} 94 | */ 95 | static Number aggregate(Object[] array, String key, GatherAggregator aggregator) { 96 | if(array == null) { 97 | return null; 98 | } 99 | 100 | if(key == null) { 101 | return null; 102 | } 103 | 104 | if(aggregator == null) { 105 | return null; 106 | } 107 | 108 | if(array.length == 0) { 109 | return null; 110 | } 111 | 112 | int found = 0; 113 | for(Object item : array) { 114 | found = aggregateOnItem(item, key, aggregator, found); 115 | } 116 | 117 | return aggregator.getResult(found); 118 | } 119 | 120 | /** 121 | * Run the {@link GatherAggregator} over a single item from the collection. 122 | * 123 | * @param item 124 | * A single item from a collection over which we fire the aggregator 125 | * 126 | * @param key 127 | * the key to fire aggregator on 128 | * 129 | * @param aggregator 130 | * the {@link GatherAggregator} to use 131 | * 132 | * @param found 133 | * total number of items that have been found till now 134 | * 135 | * @return an integer giving total number of items found. An item is called 136 | * found if there exists an attribute on the object for the given key 137 | */ 138 | static int aggregateOnItem(T item, String key, GatherAggregator aggregator, int found) { 139 | Field field = GatherReflect.getField(item, key); 140 | if(field == null) { 141 | return found; 142 | } 143 | 144 | found++; 145 | Object value; 146 | 147 | try { 148 | // allow field to be read 149 | field.setAccessible(true); 150 | 151 | value = field.get(item); 152 | } catch (IllegalArgumentException | IllegalAccessException e) { 153 | throw new RuntimeException("Unable to read value of field", e); 154 | } 155 | 156 | aggregator.aggregate(found, value); 157 | return found; 158 | } 159 | 160 | /** 161 | * Count total number of objects that match the given {@link Gather} query. 162 | * 163 | * @param collection 164 | * collection of objects to fire query upon 165 | * 166 | * @param gather 167 | * the {@link Gather} query to fire 168 | * 169 | * @return number of objects that matched the query 170 | */ 171 | static int count(final Collection collection, final Gather gather) { 172 | ResultsOrCount resultsOrCount = getResultsInternal(collection, gather, 0, 0, true); 173 | return resultsOrCount.count; 174 | } 175 | 176 | /** 177 | * Count total number of objects that match the given {@link Gather} query. 178 | * 179 | * @param array 180 | * array of objects to fire query upon 181 | * 182 | * @param gather 183 | * the {@link Gather} query to fire 184 | * 185 | * @return number of objects that matched the query 186 | */ 187 | static int count(final T[] array, final Gather gather) { 188 | ResultsOrCount resultsOrCount = getResultsInternal(array, gather, 0, 0, true); 189 | return resultsOrCount.count; 190 | } 191 | 192 | static List getResults(final Collection collection, final Gather gather, final int numResults, final int skipCount) { 193 | ResultsOrCount resultsOrCount = getResultsInternal(collection, gather, numResults, skipCount, false); 194 | return resultsOrCount.list; 195 | } 196 | 197 | /** 198 | * The method never returns a null. 199 | * 200 | * @param collection 201 | * @param gather 202 | * @param numResults 203 | * @param skipCount 204 | * @param countMode 205 | * @return 206 | */ 207 | static ResultsOrCount getResultsInternal(final Collection collection, final Gather gather, final int numResults, final int skipCount, final boolean countMode) { 208 | ResultsOrCount resultsOrCount = new ResultsOrCount(); 209 | if(collection == null) { 210 | return resultsOrCount; 211 | } 212 | 213 | if(collection.isEmpty()) { 214 | return resultsOrCount; 215 | } 216 | 217 | // run filtering criteria first 218 | int skipped = 0; 219 | for(T item : collection) { 220 | if(matches(item, gather)) { 221 | // skip elements asked for 222 | if(skipCount > 0 && skipped < skipCount) { 223 | skipped++; 224 | continue; 225 | } 226 | 227 | // add the result - we need this item 228 | // either as count or as an actual result 229 | if(countMode) { 230 | resultsOrCount.count++; 231 | } else { 232 | resultsOrCount.add(item); 233 | } 234 | 235 | // break if we have accumulated enough results 236 | if(numResults > 0 && resultsOrCount.size() == numResults) { 237 | return resultsOrCount; 238 | } 239 | } 240 | } 241 | 242 | return resultsOrCount; 243 | } 244 | 245 | /** 246 | * The method never returns a null. 247 | * 248 | * @param collection 249 | * @param gather 250 | * @param numResults 251 | * @param skipCount 252 | * @param countMode 253 | * @return 254 | */ 255 | static ResultsOrCount getResultsInternal(final T[] collection, final Gather gather, final int numResults, final int skipCount, final boolean countMode) { 256 | ResultsOrCount resultsOrCount = new ResultsOrCount(); 257 | if(collection == null) { 258 | return resultsOrCount; 259 | } 260 | 261 | if(collection.length == 0) { 262 | return resultsOrCount; 263 | } 264 | 265 | // run filtering criteria first 266 | int skipped = 0; 267 | for(T item : collection) { 268 | if(matches(item, gather)) { 269 | // skip elements asked for 270 | if(skipCount > 0 && skipped < skipCount) { 271 | skipped++; 272 | continue; 273 | } 274 | 275 | // add the result - we need this item 276 | // either as count or as an actual result 277 | if(countMode) { 278 | resultsOrCount.count++; 279 | } else { 280 | resultsOrCount.add(item); 281 | } 282 | 283 | // break if we have accumulated enough results 284 | if(numResults > 0 && resultsOrCount.size() == numResults) { 285 | return resultsOrCount; 286 | } 287 | } 288 | } 289 | 290 | return resultsOrCount; 291 | } 292 | 293 | static boolean matches(T item, Gather gather) { 294 | if(item == null) { 295 | return false; 296 | } 297 | 298 | if(gather == null) { 299 | return false; 300 | } 301 | 302 | if(gather.criteria.isEmpty()) { 303 | return true; 304 | } 305 | 306 | boolean finalResult = false; 307 | for(GatherCriteria criteria : gather.criteria) { 308 | boolean criteriaResult = matchCriteria(item, criteria); 309 | 310 | if(criteria.inverse) { 311 | criteriaResult = !criteriaResult; 312 | } 313 | 314 | switch(criteria.join) { 315 | case OR: 316 | finalResult = criteriaResult | finalResult; 317 | break; 318 | 319 | case AND: 320 | finalResult = criteriaResult & finalResult; 321 | break; 322 | 323 | } 324 | } 325 | 326 | return finalResult; 327 | } 328 | 329 | /** 330 | * 331 | * @param item an always non-null object 332 | * 333 | * @param criteria 334 | * @param classOfT 335 | * @return 336 | */ 337 | static boolean matchCriteria(T item, GatherCriteria criteria) { 338 | FieldAndInstance fieldAndInstance = GatherReflect.getFieldAndInstance(item, criteria.key); 339 | 340 | if(criteria.operation == GatherOperation.HasProperty) { 341 | if(fieldAndInstance.field != null) { 342 | return true; 343 | } 344 | 345 | return false; 346 | } 347 | 348 | if(fieldAndInstance.field == null) { 349 | return false; 350 | } 351 | 352 | // allow field to be read 353 | fieldAndInstance.field.setAccessible(true); 354 | 355 | // get the value from the object instance 356 | Object value; 357 | try { 358 | value = fieldAndInstance.field.get(fieldAndInstance.instance); 359 | } catch (IllegalArgumentException | IllegalAccessException e) { 360 | throw new RuntimeException("Unable to read value of field", e); 361 | } 362 | 363 | // now match the value against criteria values 364 | return valueMatchesCriteria(value, criteria.operation, criteria.value); 365 | } 366 | 367 | static boolean valueMatchesCriteria(Object fieldValue, GatherOperation operation, Object requiredValue) { 368 | switch(operation) { 369 | case Equals: 370 | return handleEquals(fieldValue, requiredValue); 371 | 372 | case EqualsIgnoreCase: 373 | return handleEqualsIgnoreCase(fieldValue, requiredValue); 374 | 375 | case GreaterThan: 376 | return handleGreaterThan(fieldValue, requiredValue); 377 | 378 | case GreaterThanOrEquals: 379 | return handleGreaterThanOrEquals(fieldValue, requiredValue); 380 | 381 | case In: 382 | return handleValueIn(fieldValue, requiredValue); 383 | 384 | case IsNull: 385 | return handleNull(fieldValue, requiredValue); 386 | 387 | case CollectionHasValue: 388 | return handleCollectionHasValue(fieldValue, requiredValue); 389 | 390 | case CollectionHasAllValues: 391 | return handleCollectionHasAllValues(fieldValue, requiredValue); 392 | 393 | case CollectionHasAnyValue: 394 | return handleCollectionHasAnyValue(fieldValue, requiredValue); 395 | 396 | case LessThan: 397 | return handleLessThan(fieldValue, requiredValue); 398 | 399 | case LessThanOrEquals: 400 | return handleLessThanOrEquals(fieldValue, requiredValue); 401 | 402 | case RegexMatch: 403 | return handleRegexMatch(fieldValue, requiredValue); 404 | 405 | case WildcardMatch: 406 | return handleWildcardMatch(fieldValue, requiredValue); 407 | 408 | case HasProperty: 409 | throw new IllegalStateException("This operation should have been taken care of before"); 410 | 411 | default: 412 | throw new IllegalStateException("Unknown operation in criteria: " + operation); 413 | 414 | } 415 | } 416 | 417 | static boolean handleCollectionHasAnyValue(Object fieldValue, Object requiredValue) { 418 | return handleCollectionHasAllOrAnyValues(fieldValue, requiredValue, false); 419 | } 420 | 421 | static boolean handleCollectionHasAllValues(Object fieldValue, Object requiredValue) { 422 | return handleCollectionHasAllOrAnyValues(fieldValue, requiredValue, true); 423 | } 424 | 425 | static boolean handleCollectionHasAllOrAnyValues(Object fieldValue, Object requiredValue, boolean usingAllClause) { 426 | if(fieldValue == null) { 427 | return false; 428 | } 429 | 430 | if(requiredValue == null) { 431 | return false; 432 | } 433 | 434 | // check for collection 435 | if(fieldValue instanceof Collection) { 436 | Collection collection = (Collection) fieldValue; 437 | 438 | return GatherUtils.containsAllOrAny(collection, requiredValue, usingAllClause); 439 | } 440 | 441 | // check for array 442 | if(fieldValue.getClass().isArray()) { 443 | if(fieldValue instanceof Object[]) { 444 | return GatherUtils.containsAllOrAny((Object[]) fieldValue, requiredValue, usingAllClause); 445 | } 446 | 447 | if(fieldValue instanceof char[]) { 448 | return GatherUtils.containsAllOrAny((char[]) fieldValue, requiredValue, usingAllClause); 449 | } 450 | 451 | if(fieldValue instanceof boolean[]) { 452 | return GatherUtils.containsAllOrAny((boolean[]) fieldValue, requiredValue, usingAllClause); 453 | } 454 | 455 | if(fieldValue instanceof byte[]) { 456 | return GatherUtils.containsAllOrAny((byte[]) fieldValue, requiredValue, usingAllClause); 457 | } 458 | 459 | if(fieldValue instanceof int[]) { 460 | return GatherUtils.containsAllOrAny((int[]) fieldValue, requiredValue, usingAllClause); 461 | } 462 | 463 | if(fieldValue instanceof short[]) { 464 | return GatherUtils.containsAllOrAny((short[]) fieldValue, requiredValue, usingAllClause); 465 | } 466 | 467 | if(fieldValue instanceof long[]) { 468 | return GatherUtils.containsAllOrAny((long[]) fieldValue, requiredValue, usingAllClause); 469 | } 470 | 471 | if(fieldValue instanceof float[]) { 472 | return GatherUtils.containsAllOrAny((float[]) fieldValue, requiredValue, usingAllClause); 473 | } 474 | 475 | if(fieldValue instanceof double[]) { 476 | return GatherUtils.containsAllOrAny((double[]) fieldValue, requiredValue, usingAllClause); 477 | } 478 | } 479 | 480 | // not sure what to do 481 | return false; 482 | } 483 | 484 | /** 485 | * Check if the given collection or array has the value provided. 486 | * 487 | * @param fieldValue 488 | * @param requiredValue 489 | * @return 490 | */ 491 | static boolean handleCollectionHasValue(Object fieldValue, Object requiredValue) { 492 | if(fieldValue == null) { 493 | return false; 494 | } 495 | 496 | if(requiredValue == null) { 497 | return false; 498 | } 499 | 500 | // check for collection 501 | if(fieldValue instanceof Collection) { 502 | Collection collection = (Collection) fieldValue; 503 | 504 | return collection.contains(requiredValue); 505 | } 506 | 507 | // check for array 508 | if(fieldValue.getClass().isArray()) { 509 | if(fieldValue instanceof Object[]) { 510 | return GatherUtils.contains((Object[]) fieldValue, requiredValue); 511 | } 512 | 513 | if(fieldValue instanceof char[]) { 514 | return GatherUtils.contains((char[]) fieldValue, requiredValue); 515 | } 516 | 517 | if(fieldValue instanceof boolean[]) { 518 | return GatherUtils.contains((boolean[]) fieldValue, requiredValue); 519 | } 520 | 521 | // primitive number arrays can only contain numbers 522 | if(!(requiredValue instanceof Number)) { 523 | return false; 524 | } 525 | 526 | final Number number = (Number) requiredValue; 527 | 528 | if(fieldValue instanceof byte[]) { 529 | return GatherUtils.contains((byte[]) fieldValue, number); 530 | } 531 | 532 | if(fieldValue instanceof short[]) { 533 | return GatherUtils.contains((short[]) fieldValue, number); 534 | } 535 | 536 | if(fieldValue instanceof int[]) { 537 | return GatherUtils.contains((int[]) fieldValue, number); 538 | } 539 | 540 | if(fieldValue instanceof long[]) { 541 | return GatherUtils.contains((long[]) fieldValue, number); 542 | } 543 | 544 | if(fieldValue instanceof float[]) { 545 | return GatherUtils.contains((float[]) fieldValue, number); 546 | } 547 | 548 | if(fieldValue instanceof double[]) { 549 | return GatherUtils.contains((double[]) fieldValue, number); 550 | } 551 | } 552 | 553 | // not sure what to do 554 | return false; 555 | } 556 | 557 | /** 558 | * Handle wildcard match between field and the value. 559 | * 560 | * @param fieldValue 561 | * @param requiredValue 562 | * @return 563 | */ 564 | static boolean handleWildcardMatch(Object fieldValue, Object requiredValue) { 565 | if(fieldValue == null) { 566 | return false; 567 | } 568 | 569 | if(requiredValue == null) { 570 | return false; 571 | } 572 | 573 | String value = fieldValue.toString(); 574 | String pattern = requiredValue.toString(); 575 | 576 | return GatherUtils.wildcardMatch(value, pattern); 577 | } 578 | 579 | static boolean handleRegexMatch(Object fieldValue, Object requiredValue) { 580 | if(fieldValue == null) { 581 | return false; 582 | } 583 | 584 | if(requiredValue == null) { 585 | return false; 586 | } 587 | 588 | String value = fieldValue.toString(); 589 | 590 | if(requiredValue instanceof Pattern) { 591 | return GatherUtils.regexMatch(value, (Pattern) requiredValue); 592 | } 593 | 594 | String pattern = requiredValue.toString(); 595 | 596 | return GatherUtils.regexMatch(value, pattern); 597 | } 598 | 599 | static boolean handleLessThan(Object fieldValue, Object requiredValue) { 600 | return handleNumericComparison(fieldValue, requiredValue, GatherNumericComparison.LESS_THAN); 601 | } 602 | 603 | static boolean handleGreaterThan(Object fieldValue, Object requiredValue) { 604 | return handleNumericComparison(fieldValue, requiredValue, GatherNumericComparison.GREATER_THAN); 605 | } 606 | 607 | static boolean handleLessThanOrEquals(Object fieldValue, Object requiredValue) { 608 | return handleNumericComparison(fieldValue, requiredValue, GatherNumericComparison.LESS_THAN_OR_EQUALS); 609 | } 610 | 611 | static boolean handleGreaterThanOrEquals(Object fieldValue, Object requiredValue) { 612 | return handleNumericComparison(fieldValue, requiredValue, GatherNumericComparison.GREATER_THAN_OR_EQUALS); 613 | } 614 | 615 | static boolean handleNumericComparison(Object fieldValue, Object requiredValue, GatherNumericComparison compareOperation) { 616 | if(fieldValue == null) { 617 | return false; 618 | } 619 | 620 | if(requiredValue == null) { 621 | return false; 622 | } 623 | 624 | if(fieldValue instanceof Number) { 625 | if(!(requiredValue instanceof Number)) { 626 | return false; 627 | } 628 | 629 | int result = GatherUtils.compareNumbers((Number) fieldValue, (Number) requiredValue); 630 | return compareOperation.test(result); 631 | } 632 | 633 | if(fieldValue instanceof Comparable) { 634 | @SuppressWarnings("unchecked") 635 | Comparable comparable = (Comparable) fieldValue; 636 | 637 | int result = comparable.compareTo(requiredValue); 638 | return compareOperation.test(result); 639 | } 640 | 641 | // TODO: handle when comparable is not implemented 642 | return false; 643 | } 644 | 645 | /** 646 | * Test if the field value is one of the values in given required values 647 | * 648 | * @param fieldValue 649 | * the value of the field being tested 650 | * 651 | * @param requiredValue 652 | * a group/collection/array of positive values 653 | * 654 | * @return true if field value is present in collection, 655 | * false otherwise 656 | */ 657 | static boolean handleValueIn(Object fieldValue, Object requiredValue) { 658 | if(fieldValue == null) { 659 | return false; 660 | } 661 | 662 | if(requiredValue == null) { 663 | return false; 664 | } 665 | 666 | if(requiredValue instanceof Collection) { 667 | Collection collection = (Collection) requiredValue; 668 | if(collection.isEmpty()) { 669 | return false; 670 | } 671 | 672 | return collection.contains(fieldValue); 673 | } 674 | 675 | if(requiredValue instanceof Object[]) { 676 | Object[] array = (Object[]) requiredValue; 677 | 678 | return GatherUtils.contains(array, fieldValue); 679 | } 680 | 681 | // TODO: handle primitive arrays 682 | return false; 683 | } 684 | 685 | /** 686 | * Test if the field value is null or not. 687 | * 688 | * @param fieldValue 689 | * the value of the field being tested 690 | * 691 | * @param requiredValue 692 | * the expected value from query - in this case always 693 | * null 694 | * 695 | * @return true if field value is null, 696 | * false otherwise 697 | */ 698 | static boolean handleNull(Object fieldValue, Object requiredValue) { 699 | if(fieldValue == null) { 700 | return true; 701 | } 702 | 703 | return false; 704 | } 705 | 706 | /** 707 | * Test if the given objects are equal or not, ignoring the case. 708 | * 709 | * @param fieldValue 710 | * the value of the field being tested 711 | * 712 | * @param requiredValue 713 | * the expected value from query 714 | * 715 | * @return true if they are equal, false otherwise 716 | */ 717 | static boolean handleEqualsIgnoreCase(Object fieldValue, Object requiredValue) { 718 | if(fieldValue == null) { 719 | return false; 720 | } 721 | 722 | if(requiredValue == null) { 723 | return false; 724 | } 725 | 726 | if(fieldValue instanceof String) { 727 | String str = (String) fieldValue; 728 | return str.equalsIgnoreCase(requiredValue.toString()); 729 | } 730 | 731 | return handleEquals(fieldValue, requiredValue); 732 | } 733 | 734 | /** 735 | * Test if the given objects are equal or not. 736 | * 737 | * @param fieldValue 738 | * the value of the field being tested 739 | * 740 | * @param requiredValue 741 | * the expected value from query 742 | * 743 | * @return true if they are equal, false otherwise 744 | */ 745 | static boolean handleEquals(Object fieldValue, Object requiredValue) { 746 | if(fieldValue == null) { 747 | return false; 748 | } 749 | 750 | if(requiredValue == null) { 751 | return false; 752 | } 753 | 754 | if(fieldValue.equals(requiredValue)) { 755 | return true; 756 | } 757 | 758 | return false; 759 | } 760 | 761 | private static class ResultsOrCount { 762 | 763 | final List list = new ArrayList<>();; 764 | 765 | int count = 0; 766 | 767 | public void add(T item) { 768 | this.list.add(item); 769 | } 770 | 771 | public int size() { 772 | return this.list.size(); 773 | } 774 | } 775 | } 776 | -------------------------------------------------------------------------------- /src/main/java/com/sangupta/gather/GatherNumericComparison.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | /** 25 | * 26 | * @author sangupta 27 | * 28 | * @since 1.0.0 29 | */ 30 | interface GatherNumericComparison { 31 | 32 | static final GatherNumericComparison LESS_THAN = new GatherNumericComparison() { 33 | 34 | @Override 35 | public boolean test(int value) { 36 | if(value < 0) { 37 | return true; 38 | } 39 | 40 | return false; 41 | } 42 | 43 | }; 44 | 45 | static final GatherNumericComparison LESS_THAN_OR_EQUALS = new GatherNumericComparison() { 46 | 47 | @Override 48 | public boolean test(int value) { 49 | if(value <= 0) { 50 | return true; 51 | } 52 | 53 | return false; 54 | } 55 | 56 | }; 57 | 58 | static final GatherNumericComparison GREATER_THAN = new GatherNumericComparison() { 59 | 60 | @Override 61 | public boolean test(int value) { 62 | if(value > 0) { 63 | return true; 64 | } 65 | 66 | return false; 67 | } 68 | 69 | }; 70 | 71 | static final GatherNumericComparison GREATER_THAN_OR_EQUALS = new GatherNumericComparison() { 72 | 73 | @Override 74 | public boolean test(int value) { 75 | if(value >= 0) { 76 | return true; 77 | } 78 | 79 | return false; 80 | } 81 | }; 82 | 83 | public boolean test(int value); 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/sangupta/gather/GatherOperation.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | /** 25 | * 26 | * @author sangupta 27 | * 28 | * @since 1.0.0 29 | * 30 | */ 31 | enum GatherOperation { 32 | 33 | CollectionHasValue, 34 | 35 | CollectionHasAllValues, 36 | 37 | CollectionHasAnyValue, 38 | 39 | HasProperty, 40 | 41 | IsNull, 42 | 43 | Equals, 44 | 45 | EqualsIgnoreCase, 46 | 47 | WildcardMatch, 48 | 49 | RegexMatch, 50 | 51 | LessThan, 52 | 53 | LessThanOrEquals, 54 | 55 | GreaterThan, 56 | 57 | GreaterThanOrEquals, 58 | 59 | In; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/sangupta/gather/GatherReflect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | import java.lang.reflect.Field; 25 | import java.util.ArrayList; 26 | import java.util.Arrays; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | import java.util.Map; 30 | 31 | /** 32 | * Collection of Java Reflection methods that are used within {@link Gather} 33 | * framework. 34 | * 35 | * @author sangupta 36 | * 37 | * @since 1.0.0 38 | */ 39 | abstract class GatherReflect { 40 | 41 | static final Map, Map> CLASS_FIELD_KEY_CACHE = new HashMap<>(); 42 | 43 | static class FieldAndInstance { 44 | 45 | final Field field; 46 | 47 | final Object instance; 48 | 49 | FieldAndInstance(Field field, Object instance) { 50 | this.field = field; 51 | this.instance = instance; 52 | } 53 | } 54 | 55 | static FieldAndInstance getFieldAndInstance(T item, String key) { 56 | if (item == null) { 57 | return null; 58 | } 59 | 60 | if (key == null) { 61 | return null; 62 | } 63 | 64 | if (!key.contains(".")) { 65 | // this is a plain request 66 | return new FieldAndInstance(getField(item, key), item); 67 | } 68 | 69 | // this is a composed object 70 | String[] tokens = key.split("\\."); 71 | 72 | Object instance = item; 73 | Field field = null; 74 | 75 | for (int index = 0; index < tokens.length; index++) { 76 | String token = tokens[index]; 77 | field = getField(instance, token); 78 | if (field == null) { 79 | return null; 80 | } 81 | 82 | if (index == tokens.length - 1) { 83 | // this is the last token 84 | return new FieldAndInstance(field, instance); 85 | } 86 | 87 | field.setAccessible(true); 88 | 89 | try { 90 | instance = field.get(instance); 91 | } catch (IllegalArgumentException | IllegalAccessException e) { 92 | throw new RuntimeException("Unable to get hold of field from class"); 93 | } 94 | } 95 | 96 | return null; 97 | } 98 | 99 | static Field getField(T item, String key) { 100 | if (item == null) { 101 | return null; 102 | } 103 | 104 | if (key == null || key.trim().isEmpty()) { 105 | return null; 106 | } 107 | 108 | Map classCache = CLASS_FIELD_KEY_CACHE.get(item.getClass()); 109 | if (classCache != null) { 110 | return classCache.get(key); 111 | } 112 | 113 | if (key.contains(".")) { 114 | // TODO: this is a composed object 115 | return null; 116 | } 117 | 118 | // class based cache does not exist 119 | Map fieldCache = new HashMap<>(); 120 | CLASS_FIELD_KEY_CACHE.put(item.getClass(), fieldCache); 121 | 122 | Class classOfT = item.getClass(); 123 | List fields = getAllFields(classOfT); 124 | if (fields == null || fields.isEmpty()) { 125 | return null; 126 | } 127 | 128 | for (Field field : fields) { 129 | fieldCache.put(field.getName(), field); 130 | } 131 | 132 | return fieldCache.get(key); 133 | } 134 | 135 | static List getAllFields(Class clazz) { 136 | if (clazz == null) { 137 | return null; 138 | } 139 | 140 | List fields = new ArrayList<>(); 141 | populateAllFields(clazz, fields); 142 | 143 | return fields; 144 | } 145 | 146 | static void populateAllFields(Class clazz, List fields) { 147 | if (clazz == null) { 148 | return; 149 | } 150 | 151 | if (fields == null) { 152 | throw new IllegalArgumentException("List to store fields in cannot be null"); 153 | } 154 | 155 | Field[] array = clazz.getDeclaredFields(); 156 | if (array != null && array.length > 0) { 157 | fields.addAll(Arrays.asList(array)); 158 | } 159 | 160 | if (clazz.getSuperclass() == null) { 161 | return; 162 | } 163 | 164 | populateAllFields(clazz.getSuperclass(), fields); 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/com/sangupta/gather/GatherSiblingJoin.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | /** 25 | * 26 | * @author sangupta 27 | * 28 | * @since 1.0.0 29 | */ 30 | enum GatherSiblingJoin { 31 | 32 | AND, 33 | 34 | OR; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/sangupta/gather/GatherUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | import java.math.BigDecimal; 25 | import java.util.Collection; 26 | import java.util.HashMap; 27 | import java.util.Map; 28 | import java.util.concurrent.atomic.AtomicInteger; 29 | import java.util.concurrent.atomic.AtomicLong; 30 | import java.util.regex.Matcher; 31 | import java.util.regex.Pattern; 32 | 33 | /** 34 | * Utility functions for the Gather library. 35 | * 36 | * @author sangupta 37 | * 38 | * @since 1.0.0 39 | */ 40 | abstract class GatherUtils { 41 | 42 | final static Map COMPILED_PATTERNS = new HashMap<>(); 43 | 44 | final static Object[] NUMBER_TYPES = new Object[] { Integer.class, Long.class, Byte.class, Short.class, 45 | Float.class, Double.class, AtomicLong.class, AtomicInteger.class 46 | }; 47 | 48 | static boolean contains(char[] array, Object value) { 49 | if(array == null) { 50 | return false; 51 | } 52 | 53 | if(value == null) { 54 | return false; 55 | } 56 | 57 | if(value instanceof Character) { 58 | char val = (Character) value; 59 | for(char item : array) { 60 | if(item == val) { 61 | return true; 62 | } 63 | } 64 | } 65 | 66 | return false; 67 | } 68 | 69 | static boolean contains(boolean[] array, Object value) { 70 | if(array == null) { 71 | return false; 72 | } 73 | 74 | if(value == null) { 75 | return false; 76 | } 77 | 78 | if(value instanceof Boolean) { 79 | boolean val = (Boolean) value; 80 | for(boolean item : array) { 81 | if(item == val) { 82 | return true; 83 | } 84 | } 85 | } 86 | 87 | return false; 88 | } 89 | 90 | static boolean contains(byte[] array, Object value) { 91 | if(value == null) { 92 | return false; 93 | } 94 | 95 | if(value instanceof Number) { 96 | return contains(array, (Number) value); 97 | } 98 | 99 | return false; 100 | } 101 | 102 | static boolean contains(byte[] array, Number value) { 103 | if(array == null) { 104 | return false; 105 | } 106 | 107 | if(value == null) { 108 | return false; 109 | } 110 | 111 | byte val = value.byteValue(); 112 | for(byte item : array) { 113 | if(item == val) { 114 | return true; 115 | } 116 | } 117 | 118 | return false; 119 | } 120 | 121 | static boolean contains(short[] array, Object value) { 122 | if(value == null) { 123 | return false; 124 | } 125 | 126 | if(value instanceof Number) { 127 | return contains(array, (Number) value); 128 | } 129 | 130 | return false; 131 | } 132 | 133 | static boolean contains(short[] array, Number value) { 134 | if(array == null) { 135 | return false; 136 | } 137 | 138 | if(value == null) { 139 | return false; 140 | } 141 | 142 | short val = value.shortValue(); 143 | for(short item : array) { 144 | if(item == val) { 145 | return true; 146 | } 147 | } 148 | 149 | return false; 150 | } 151 | 152 | static boolean contains(int[] array, Object value) { 153 | if(value == null) { 154 | return false; 155 | } 156 | 157 | if(value instanceof Number) { 158 | return contains(array, (Number) value); 159 | } 160 | 161 | return false; 162 | } 163 | 164 | static boolean contains(int[] array, Number value) { 165 | if(array == null) { 166 | return false; 167 | } 168 | 169 | if(value == null) { 170 | return false; 171 | } 172 | 173 | int val = value.intValue(); 174 | for(int item : array) { 175 | if(item == val) { 176 | return true; 177 | } 178 | } 179 | 180 | return false; 181 | } 182 | 183 | static boolean contains(long[] array, Object value) { 184 | if(value == null) { 185 | return false; 186 | } 187 | 188 | if(value instanceof Number) { 189 | return contains(array, (Number) value); 190 | } 191 | 192 | return false; 193 | } 194 | 195 | static boolean contains(long[] array, Number value) { 196 | if(array == null) { 197 | return false; 198 | } 199 | 200 | if(value == null) { 201 | return false; 202 | } 203 | 204 | long val = value.longValue(); 205 | for(long item : array) { 206 | if(item == val) { 207 | return true; 208 | } 209 | } 210 | 211 | return false; 212 | } 213 | 214 | static boolean contains(float[] array, Object value) { 215 | if(value == null) { 216 | return false; 217 | } 218 | 219 | if(value instanceof Number) { 220 | return contains(array, (Number) value); 221 | } 222 | 223 | return false; 224 | } 225 | 226 | static boolean contains(float[] array, Number value) { 227 | if(array == null) { 228 | return false; 229 | } 230 | 231 | if(value == null) { 232 | return false; 233 | } 234 | 235 | float val = value.floatValue(); 236 | for(float item : array) { 237 | if(item == val) { 238 | return true; 239 | } 240 | } 241 | 242 | return false; 243 | } 244 | 245 | static boolean contains(double[] array, Object value) { 246 | if(value == null) { 247 | return false; 248 | } 249 | 250 | if(value instanceof Number) { 251 | return contains(array, (Number) value); 252 | } 253 | 254 | return false; 255 | } 256 | 257 | static boolean contains(double[] array, Number value) { 258 | if(array == null) { 259 | return false; 260 | } 261 | 262 | if(value == null) { 263 | return false; 264 | } 265 | 266 | double val = value.doubleValue(); 267 | for(double item : array) { 268 | if(item == val) { 269 | return true; 270 | } 271 | } 272 | 273 | return false; 274 | } 275 | 276 | static boolean contains(Object[] array, Object valueToCheck) { 277 | if(array == null) { 278 | return false; 279 | } 280 | 281 | if(array.length == 0) { 282 | return false; 283 | } 284 | 285 | for(Object item : array) { 286 | if(item == null) { 287 | continue; 288 | } 289 | 290 | if(item.equals(valueToCheck)) { 291 | return true; 292 | } 293 | } 294 | 295 | return false; 296 | } 297 | 298 | static boolean wildcardMatch(final String string, final String pattern) { 299 | int i = 0; 300 | int j = 0; 301 | int starIndex = -1; 302 | int iIndex = -1; 303 | 304 | final int stringLength = string.length(); 305 | final int patternLength = pattern.length(); 306 | 307 | final char[] stringArray = string.toCharArray(); 308 | final char[] patternArray = pattern.toCharArray(); 309 | 310 | while (i < stringLength) { 311 | if (j < patternLength && (patternArray[j] == '?' || patternArray[j] == stringArray[i])) { 312 | ++i; 313 | ++j; 314 | } else if (j < patternLength && patternArray[j] == '*') { 315 | starIndex = j; 316 | iIndex = i; 317 | j++; 318 | } else if (starIndex != -1) { 319 | j = starIndex + 1; 320 | i = iIndex+1; 321 | iIndex++; 322 | } else { 323 | return false; 324 | } 325 | } 326 | 327 | while (j < patternLength && patternArray[j] == '*') { 328 | ++j; 329 | } 330 | 331 | return j == patternLength; 332 | } 333 | 334 | public static boolean regexMatch(String value, Pattern pattern) { 335 | if(pattern == null) { 336 | return false; 337 | } 338 | 339 | if(value == null) { 340 | return false; 341 | } 342 | 343 | Matcher matcher = pattern.matcher(value); 344 | if(matcher == null) { 345 | return false; 346 | } 347 | 348 | return matcher.matches(); 349 | } 350 | 351 | public static boolean regexMatch(String value, String pattern) { 352 | if(pattern == null) { 353 | return false; 354 | } 355 | 356 | if(value == null) { 357 | return false; 358 | } 359 | 360 | Pattern compiled = COMPILED_PATTERNS.get(pattern); 361 | if(compiled == null) { 362 | compiled = Pattern.compile(pattern); 363 | COMPILED_PATTERNS.put(pattern, compiled); 364 | } 365 | 366 | return regexMatch(value, compiled); 367 | } 368 | 369 | public static boolean isNumberType(Object object) { 370 | if(object == null) { 371 | return false; 372 | } 373 | 374 | return contains(NUMBER_TYPES, object.getClass()); 375 | } 376 | 377 | public static Number asNumber(Object object) { 378 | if(object == null) { 379 | return null; 380 | } 381 | 382 | if(!isNumberType(object)) { 383 | return null; 384 | } 385 | 386 | if(object instanceof AtomicLong) { 387 | return ((AtomicLong) object).get(); 388 | } else if(object instanceof AtomicInteger) { 389 | return ((AtomicInteger) object).get(); 390 | } else if(object instanceof Number) { 391 | return (Number) object; 392 | } 393 | 394 | return null; 395 | } 396 | 397 | static boolean containsAllOrAny(boolean[] array, Object value, boolean usingAllClause) { 398 | if(array == null) { 399 | return false; 400 | } 401 | 402 | if(array.length == 0) { 403 | return false; 404 | } 405 | 406 | if(value == null) { 407 | return false; 408 | } 409 | 410 | if(value instanceof boolean[]) { 411 | boolean[] required = (boolean[]) value; 412 | 413 | boolean result; 414 | if(usingAllClause) { 415 | result = true; 416 | } else { 417 | result = false; 418 | } 419 | 420 | for(boolean item : required) { 421 | boolean itemResult = contains(array, item); 422 | 423 | if(usingAllClause) { 424 | result = result & itemResult; 425 | } else { 426 | result = result | itemResult; 427 | } 428 | } 429 | 430 | return result; 431 | } 432 | 433 | if(value instanceof Boolean[]) { 434 | Boolean[] required = (Boolean[]) value; 435 | 436 | boolean result; 437 | if(usingAllClause) { 438 | result = true; 439 | } else { 440 | result = false; 441 | } 442 | 443 | for(boolean item : required) { 444 | boolean itemResult = contains(array, item); 445 | 446 | if(usingAllClause) { 447 | result = result & itemResult; 448 | } else { 449 | result = result | itemResult; 450 | } 451 | } 452 | 453 | return result; 454 | } 455 | 456 | if(value instanceof Collection) { 457 | Collection required = (Collection) value; 458 | 459 | boolean result; 460 | if(usingAllClause) { 461 | result = true; 462 | } else { 463 | result = false; 464 | } 465 | 466 | for(Object item : required) { 467 | boolean itemResult; 468 | if(item instanceof Boolean) { 469 | itemResult = contains(array, item); 470 | } else { 471 | itemResult = false; 472 | } 473 | 474 | if(usingAllClause) { 475 | result = result & itemResult; 476 | } else { 477 | result = result | itemResult; 478 | } 479 | } 480 | 481 | return result; 482 | } 483 | 484 | return false; 485 | } 486 | 487 | static boolean containsAllOrAny(char[] array, Object value, boolean usingAllClause) { 488 | if(array == null) { 489 | return false; 490 | } 491 | 492 | if(array.length == 0) { 493 | return false; 494 | } 495 | 496 | if(value == null) { 497 | return false; 498 | } 499 | 500 | if(value instanceof char[]) { 501 | char[] required = (char[]) value; 502 | 503 | boolean result; 504 | if(usingAllClause) { 505 | result = true; 506 | } else { 507 | result = false; 508 | } 509 | 510 | for(char item : required) { 511 | boolean itemResult = contains(array, item); 512 | 513 | if(usingAllClause) { 514 | result = result & itemResult; 515 | } else { 516 | result = result | itemResult; 517 | } 518 | } 519 | 520 | return result; 521 | } 522 | 523 | if(value instanceof Character[]) { 524 | Character[] required = (Character[]) value; 525 | 526 | boolean result; 527 | if(usingAllClause) { 528 | result = true; 529 | } else { 530 | result = false; 531 | } 532 | 533 | for(Character item : required) { 534 | boolean itemResult = contains(array, item); 535 | 536 | if(usingAllClause) { 537 | result = result & itemResult; 538 | } else { 539 | result = result | itemResult; 540 | } 541 | } 542 | 543 | return result; 544 | } 545 | 546 | if(value instanceof Collection) { 547 | Collection required = (Collection) value; 548 | 549 | boolean result; 550 | if(usingAllClause) { 551 | result = true; 552 | } else { 553 | result = false; 554 | } 555 | 556 | for(Object item : required) { 557 | boolean itemResult; 558 | if(item instanceof Character) { 559 | itemResult = contains(array, item); 560 | } else { 561 | itemResult = false; 562 | } 563 | 564 | if(usingAllClause) { 565 | result = result & itemResult; 566 | } else { 567 | result = result | itemResult; 568 | } 569 | } 570 | 571 | return result; 572 | } 573 | 574 | return false; 575 | } 576 | 577 | static boolean containsAllOrAny(byte[] array, Object value, boolean usingAllClause) { 578 | if(array == null) { 579 | return false; 580 | } 581 | 582 | if(array.length == 0) { 583 | return false; 584 | } 585 | 586 | if(value == null) { 587 | return false; 588 | } 589 | 590 | if(value instanceof byte[]) { 591 | byte[] required = (byte[]) value; 592 | 593 | boolean result; 594 | if(usingAllClause) { 595 | result = true; 596 | } else { 597 | result = false; 598 | } 599 | 600 | for(byte item : required) { 601 | boolean itemResult = contains(array, item); 602 | 603 | if(usingAllClause) { 604 | result = result & itemResult; 605 | } else { 606 | result = result | itemResult; 607 | } 608 | } 609 | 610 | return result; 611 | } 612 | 613 | if(value instanceof Number[]) { 614 | Number[] required = (Number[]) value; 615 | 616 | boolean result; 617 | if(usingAllClause) { 618 | result = true; 619 | } else { 620 | result = false; 621 | } 622 | 623 | for(Number item : required) { 624 | boolean itemResult = contains(array, item); 625 | 626 | if(usingAllClause) { 627 | result = result & itemResult; 628 | } else { 629 | result = result | itemResult; 630 | } 631 | } 632 | 633 | return result; 634 | } 635 | 636 | if(value instanceof Collection) { 637 | Collection required = (Collection) value; 638 | 639 | boolean result; 640 | if(usingAllClause) { 641 | result = true; 642 | } else { 643 | result = false; 644 | } 645 | 646 | for(Object item : required) { 647 | boolean itemResult; 648 | if(item instanceof Number) { 649 | itemResult = contains(array, item); 650 | } else { 651 | itemResult = false; 652 | } 653 | 654 | if(usingAllClause) { 655 | result = result & itemResult; 656 | } else { 657 | result = result | itemResult; 658 | } 659 | } 660 | 661 | return result; 662 | } 663 | 664 | return false; 665 | } 666 | 667 | static boolean containsAllOrAny(short[] array, Object value, boolean usingAllClause) { 668 | if(array == null) { 669 | return false; 670 | } 671 | 672 | if(array.length == 0) { 673 | return false; 674 | } 675 | 676 | if(value == null) { 677 | return false; 678 | } 679 | 680 | if(value instanceof short[]) { 681 | short[] required = (short[]) value; 682 | 683 | boolean result; 684 | if(usingAllClause) { 685 | result = true; 686 | } else { 687 | result = false; 688 | } 689 | 690 | for(short item : required) { 691 | boolean itemResult = contains(array, item); 692 | 693 | if(usingAllClause) { 694 | result = result & itemResult; 695 | } else { 696 | result = result | itemResult; 697 | } 698 | } 699 | 700 | return result; 701 | } 702 | 703 | if(value instanceof Number[]) { 704 | Number[] required = (Number[]) value; 705 | 706 | boolean result; 707 | if(usingAllClause) { 708 | result = true; 709 | } else { 710 | result = false; 711 | } 712 | 713 | for(Number item : required) { 714 | boolean itemResult = contains(array, item); 715 | 716 | if(usingAllClause) { 717 | result = result & itemResult; 718 | } else { 719 | result = result | itemResult; 720 | } 721 | } 722 | 723 | return result; 724 | } 725 | 726 | if(value instanceof Collection) { 727 | Collection required = (Collection) value; 728 | 729 | boolean result; 730 | if(usingAllClause) { 731 | result = true; 732 | } else { 733 | result = false; 734 | } 735 | 736 | for(Object item : required) { 737 | boolean itemResult; 738 | if(item instanceof Number) { 739 | itemResult = contains(array, item); 740 | } else { 741 | itemResult = false; 742 | } 743 | 744 | if(usingAllClause) { 745 | result = result & itemResult; 746 | } else { 747 | result = result | itemResult; 748 | } 749 | } 750 | 751 | return result; 752 | } 753 | 754 | return false; 755 | } 756 | 757 | static boolean containsAllOrAny(int[] array, Object value, boolean usingAllClause) { 758 | if(array == null) { 759 | return false; 760 | } 761 | 762 | if(array.length == 0) { 763 | return false; 764 | } 765 | 766 | if(value == null) { 767 | return false; 768 | } 769 | 770 | if(value instanceof int[]) { 771 | int[] required = (int[]) value; 772 | 773 | boolean result; 774 | if(usingAllClause) { 775 | result = true; 776 | } else { 777 | result = false; 778 | } 779 | 780 | for(int item : required) { 781 | boolean itemResult = contains(array, item); 782 | 783 | if(usingAllClause) { 784 | result = result & itemResult; 785 | } else { 786 | result = result | itemResult; 787 | } 788 | } 789 | 790 | return result; 791 | } 792 | 793 | if(value instanceof Number[]) { 794 | Number[] required = (Number[]) value; 795 | 796 | boolean result; 797 | if(usingAllClause) { 798 | result = true; 799 | } else { 800 | result = false; 801 | } 802 | 803 | for(Number item : required) { 804 | boolean itemResult = contains(array, item); 805 | 806 | if(usingAllClause) { 807 | result = result & itemResult; 808 | } else { 809 | result = result | itemResult; 810 | } 811 | } 812 | 813 | return result; 814 | } 815 | 816 | if(value instanceof Collection) { 817 | Collection required = (Collection) value; 818 | 819 | boolean result; 820 | if(usingAllClause) { 821 | result = true; 822 | } else { 823 | result = false; 824 | } 825 | 826 | for(Object item : required) { 827 | boolean itemResult; 828 | if(item instanceof Number) { 829 | itemResult = contains(array, item); 830 | } else { 831 | itemResult = false; 832 | } 833 | 834 | if(usingAllClause) { 835 | result = result & itemResult; 836 | } else { 837 | result = result | itemResult; 838 | } 839 | } 840 | 841 | return result; 842 | } 843 | 844 | return false; 845 | } 846 | 847 | static boolean containsAllOrAny(long[] array, Object value, boolean usingAllClause) { 848 | if(array == null) { 849 | return false; 850 | } 851 | 852 | if(array.length == 0) { 853 | return false; 854 | } 855 | 856 | if(value == null) { 857 | return false; 858 | } 859 | 860 | if(value instanceof long[]) { 861 | long[] required = (long[]) value; 862 | 863 | boolean result; 864 | if(usingAllClause) { 865 | result = true; 866 | } else { 867 | result = false; 868 | } 869 | 870 | for(long item : required) { 871 | boolean itemResult = contains(array, item); 872 | 873 | if(usingAllClause) { 874 | result = result & itemResult; 875 | } else { 876 | result = result | itemResult; 877 | } 878 | } 879 | 880 | return result; 881 | } 882 | 883 | if(value instanceof Number[]) { 884 | Number[] required = (Number[]) value; 885 | 886 | boolean result; 887 | if(usingAllClause) { 888 | result = true; 889 | } else { 890 | result = false; 891 | } 892 | 893 | for(Number item : required) { 894 | boolean itemResult = contains(array, item); 895 | 896 | if(usingAllClause) { 897 | result = result & itemResult; 898 | } else { 899 | result = result | itemResult; 900 | } 901 | } 902 | 903 | return result; 904 | } 905 | 906 | if(value instanceof Collection) { 907 | Collection required = (Collection) value; 908 | 909 | boolean result; 910 | if(usingAllClause) { 911 | result = true; 912 | } else { 913 | result = false; 914 | } 915 | 916 | for(Object item : required) { 917 | boolean itemResult; 918 | if(item instanceof Number) { 919 | itemResult = contains(array, item); 920 | } else { 921 | itemResult = false; 922 | } 923 | 924 | if(usingAllClause) { 925 | result = result & itemResult; 926 | } else { 927 | result = result | itemResult; 928 | } 929 | } 930 | 931 | return result; 932 | } 933 | 934 | return false; 935 | } 936 | 937 | static boolean containsAllOrAny(float[] array, Object value, boolean usingAllClause) { 938 | if(array == null) { 939 | return false; 940 | } 941 | 942 | if(array.length == 0) { 943 | return false; 944 | } 945 | 946 | if(value == null) { 947 | return false; 948 | } 949 | 950 | if(value instanceof float[]) { 951 | float[] required = (float[]) value; 952 | 953 | boolean result; 954 | if(usingAllClause) { 955 | result = true; 956 | } else { 957 | result = false; 958 | } 959 | 960 | for(float item : required) { 961 | boolean itemResult = contains(array, item); 962 | 963 | if(usingAllClause) { 964 | result = result & itemResult; 965 | } else { 966 | result = result | itemResult; 967 | } 968 | } 969 | 970 | return result; 971 | } 972 | 973 | if(value instanceof Number[]) { 974 | Number[] required = (Number[]) value; 975 | 976 | boolean result; 977 | if(usingAllClause) { 978 | result = true; 979 | } else { 980 | result = false; 981 | } 982 | 983 | for(Number item : required) { 984 | boolean itemResult = contains(array, item); 985 | 986 | if(usingAllClause) { 987 | result = result & itemResult; 988 | } else { 989 | result = result | itemResult; 990 | } 991 | } 992 | 993 | return result; 994 | } 995 | 996 | if(value instanceof Collection) { 997 | Collection required = (Collection) value; 998 | 999 | boolean result; 1000 | if(usingAllClause) { 1001 | result = true; 1002 | } else { 1003 | result = false; 1004 | } 1005 | 1006 | for(Object item : required) { 1007 | boolean itemResult; 1008 | if(item instanceof Number) { 1009 | itemResult = contains(array, item); 1010 | } else { 1011 | itemResult = false; 1012 | } 1013 | 1014 | if(usingAllClause) { 1015 | result = result & itemResult; 1016 | } else { 1017 | result = result | itemResult; 1018 | } 1019 | } 1020 | 1021 | return result; 1022 | } 1023 | 1024 | return false; 1025 | } 1026 | 1027 | static boolean containsAllOrAny(double[] array, Object value, boolean usingAllClause) { 1028 | if(array == null) { 1029 | return false; 1030 | } 1031 | 1032 | if(array.length == 0) { 1033 | return false; 1034 | } 1035 | 1036 | if(value == null) { 1037 | return false; 1038 | } 1039 | 1040 | if(value instanceof double[]) { 1041 | double[] required = (double[]) value; 1042 | 1043 | boolean result; 1044 | if(usingAllClause) { 1045 | result = true; 1046 | } else { 1047 | result = false; 1048 | } 1049 | 1050 | for(double item : required) { 1051 | boolean itemResult = contains(array, item); 1052 | 1053 | if(usingAllClause) { 1054 | result = result & itemResult; 1055 | } else { 1056 | result = result | itemResult; 1057 | } 1058 | } 1059 | 1060 | return result; 1061 | } 1062 | 1063 | if(value instanceof Number[]) { 1064 | Number[] required = (Number[]) value; 1065 | 1066 | boolean result; 1067 | if(usingAllClause) { 1068 | result = true; 1069 | } else { 1070 | result = false; 1071 | } 1072 | 1073 | for(Number item : required) { 1074 | boolean itemResult = contains(array, item); 1075 | 1076 | if(usingAllClause) { 1077 | result = result & itemResult; 1078 | } else { 1079 | result = result | itemResult; 1080 | } 1081 | } 1082 | 1083 | return result; 1084 | } 1085 | 1086 | if(value instanceof Collection) { 1087 | Collection required = (Collection) value; 1088 | 1089 | boolean result; 1090 | if(usingAllClause) { 1091 | result = true; 1092 | } else { 1093 | result = false; 1094 | } 1095 | 1096 | for(Object item : required) { 1097 | boolean itemResult; 1098 | if(item instanceof Number) { 1099 | itemResult = contains(array, item); 1100 | } else { 1101 | itemResult = false; 1102 | } 1103 | 1104 | if(usingAllClause) { 1105 | result = result & itemResult; 1106 | } else { 1107 | result = result | itemResult; 1108 | } 1109 | } 1110 | 1111 | return result; 1112 | } 1113 | 1114 | return false; 1115 | } 1116 | 1117 | static boolean containsAllOrAny(Object[] array, Object value, boolean usingAllClause) { 1118 | if(array == null) { 1119 | return false; 1120 | } 1121 | 1122 | if(array.length == 0) { 1123 | return false; 1124 | } 1125 | 1126 | if(value == null) { 1127 | return false; 1128 | } 1129 | 1130 | if(value instanceof Object[]) { 1131 | Object[] required = (Object[]) value; 1132 | 1133 | boolean result; 1134 | if(usingAllClause) { 1135 | result = true; 1136 | } else { 1137 | result = false; 1138 | } 1139 | 1140 | for(Object item : required) { 1141 | boolean itemResult = contains(array, item); 1142 | 1143 | if(usingAllClause) { 1144 | result = result & itemResult; 1145 | } else { 1146 | result = result | itemResult; 1147 | } 1148 | } 1149 | 1150 | return result; 1151 | } 1152 | 1153 | if(value instanceof Collection) { 1154 | Collection required = (Collection) value; 1155 | 1156 | boolean result; 1157 | if(usingAllClause) { 1158 | result = true; 1159 | } else { 1160 | result = false; 1161 | } 1162 | 1163 | for(Object item : required) { 1164 | boolean itemResult = contains(array, item); 1165 | 1166 | if(usingAllClause) { 1167 | result = result & itemResult; 1168 | } else { 1169 | result = result | itemResult; 1170 | } 1171 | } 1172 | 1173 | return result; 1174 | } 1175 | 1176 | return false; 1177 | } 1178 | 1179 | static boolean containsAllOrAny(Collection collection, Object value, boolean usingAllClause) { 1180 | if(collection == null) { 1181 | return false; 1182 | } 1183 | 1184 | if(collection.size() == 0) { 1185 | return false; 1186 | } 1187 | 1188 | if(value == null) { 1189 | return false; 1190 | } 1191 | 1192 | if(value instanceof Object[]) { 1193 | Object[] required = (Object[]) value; 1194 | 1195 | boolean result; 1196 | if(usingAllClause) { 1197 | result = true; 1198 | } else { 1199 | result = false; 1200 | } 1201 | 1202 | for(Object item : required) { 1203 | boolean itemResult = collection.contains(item); 1204 | 1205 | if(usingAllClause) { 1206 | result = result & itemResult; 1207 | } else { 1208 | result = result | itemResult; 1209 | } 1210 | } 1211 | 1212 | return result; 1213 | } 1214 | 1215 | if(value instanceof Collection) { 1216 | Collection required = (Collection) value; 1217 | 1218 | boolean result; 1219 | if(usingAllClause) { 1220 | result = true; 1221 | } else { 1222 | result = false; 1223 | } 1224 | 1225 | for(Object item : required) { 1226 | boolean itemResult = collection.contains(item); 1227 | 1228 | if(usingAllClause) { 1229 | result = result & itemResult; 1230 | } else { 1231 | result = result | itemResult; 1232 | } 1233 | } 1234 | 1235 | return result; 1236 | } 1237 | 1238 | return false; 1239 | } 1240 | 1241 | public static int compareNumbers(Number fieldValue, Number requiredValue) { 1242 | if(fieldValue instanceof Byte) { 1243 | Byte field = fieldValue.byteValue(); 1244 | Byte required = requiredValue.byteValue(); 1245 | 1246 | return field.compareTo(required); 1247 | } 1248 | 1249 | if(fieldValue instanceof Short) { 1250 | Short field = fieldValue.shortValue(); 1251 | Short required = requiredValue.shortValue(); 1252 | 1253 | return field.compareTo(required); 1254 | } 1255 | 1256 | if(fieldValue instanceof Integer) { 1257 | Integer field = fieldValue.intValue(); 1258 | Integer required = requiredValue.intValue(); 1259 | 1260 | return field.compareTo(required); 1261 | } 1262 | 1263 | if(fieldValue instanceof Long) { 1264 | Long field = fieldValue.longValue(); 1265 | Long required = requiredValue.longValue(); 1266 | 1267 | return field.compareTo(required); 1268 | } 1269 | 1270 | if(fieldValue instanceof Float) { 1271 | Float field = fieldValue.floatValue(); 1272 | Float required = requiredValue.floatValue(); 1273 | 1274 | return field.compareTo(required); 1275 | } 1276 | 1277 | if(fieldValue instanceof Double) { 1278 | Double field = fieldValue.doubleValue(); 1279 | Double required = requiredValue.doubleValue(); 1280 | 1281 | return field.compareTo(required); 1282 | } 1283 | 1284 | if(fieldValue instanceof AtomicInteger) { 1285 | Integer field = ((AtomicInteger) fieldValue).intValue(); 1286 | Integer required = requiredValue.intValue(); 1287 | 1288 | return field.compareTo(required); 1289 | } 1290 | 1291 | if(fieldValue instanceof AtomicLong) { 1292 | Long field = ((AtomicLong) fieldValue).longValue(); 1293 | Long required = requiredValue.longValue(); 1294 | 1295 | return field.compareTo(required); 1296 | } 1297 | 1298 | if(fieldValue instanceof BigDecimal) { 1299 | BigDecimal field = (BigDecimal) fieldValue; 1300 | 1301 | if(requiredValue instanceof BigDecimal) { 1302 | return field.compareTo((BigDecimal) requiredValue); 1303 | } 1304 | 1305 | if(requiredValue instanceof Byte) { 1306 | return field.compareTo(new BigDecimal(requiredValue.byteValue())); 1307 | } 1308 | 1309 | if(requiredValue instanceof Short) { 1310 | return field.compareTo(new BigDecimal(requiredValue.shortValue())); 1311 | } 1312 | 1313 | if(requiredValue instanceof Integer) { 1314 | return field.compareTo(new BigDecimal(requiredValue.intValue())); 1315 | } 1316 | 1317 | if(requiredValue instanceof Long) { 1318 | return field.compareTo(new BigDecimal(requiredValue.longValue())); 1319 | } 1320 | 1321 | if(requiredValue instanceof Float) { 1322 | return field.compareTo(new BigDecimal(requiredValue.floatValue())); 1323 | } 1324 | 1325 | if(requiredValue instanceof Double) { 1326 | return field.compareTo(new BigDecimal(requiredValue.doubleValue())); 1327 | } 1328 | 1329 | if(requiredValue instanceof AtomicInteger) { 1330 | return field.compareTo(new BigDecimal(requiredValue.intValue())); 1331 | } 1332 | 1333 | if(requiredValue instanceof AtomicLong) { 1334 | return field.compareTo(new BigDecimal(requiredValue.longValue())); 1335 | } 1336 | } 1337 | 1338 | // TODO: allow adding converter for handling numbers 1339 | throw new RuntimeException("Cannot compare values of type " + fieldValue.getClass() + " and " + requiredValue.getClass()); 1340 | } 1341 | 1342 | } 1343 | -------------------------------------------------------------------------------- /src/test/java/com/sangupta/gather/TestGather.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | import java.util.ArrayList; 25 | import java.util.Arrays; 26 | import java.util.List; 27 | import java.util.regex.Pattern; 28 | 29 | import org.junit.Assert; 30 | import org.junit.Test; 31 | 32 | public class TestGather { 33 | 34 | public static void main(String[] args) { 35 | Gather query = Gather.where("name").in(new Object[] { "Amit Modi", "Sandeep Gupta" }).and("salary").lessThanOrEquals(20d); 36 | List result = query.find(getWorkers()); 37 | for(Worker worker : result) { 38 | System.out.println(worker); 39 | } 40 | } 41 | 42 | @Test 43 | public void testGatherLimitedResults() { 44 | final List workers = getWorkers(); 45 | 46 | Assert.assertEquals(2, Gather.where("age").is(36).find(workers).size()); 47 | Assert.assertNotNull(Gather.where("age").is(36).findOne(workers)); 48 | Assert.assertNotNull(Gather.where("age").is(36).findOne(workers, 1)); 49 | Assert.assertNull(Gather.where("age").is(36).findOne(workers, 2)); 50 | Assert.assertNull(Gather.where("age").is(36).findOne(workers, 10)); 51 | 52 | Assert.assertNotNull(Gather.where("age").is(36).find(workers, 1)); 53 | Assert.assertNotNull(Gather.where("age").is(36).find(workers, 1, 1)); 54 | } 55 | 56 | @Test 57 | public void testGatherAggregation() { 58 | final List workers = getWorkers(); 59 | final Worker[] arrayOfWorkers = workers.toArray(new Worker[] {}); 60 | 61 | // on list first 62 | GatherAggregator aggregator = new GatherAggregator.CountingAggregator(); 63 | Gather.aggregate(workers, "age", aggregator); 64 | Assert.assertEquals(4, aggregator.getResult(0)); 65 | 66 | Assert.assertEquals(150l, Gather.sumAsLong(workers, "age")); 67 | Assert.assertEquals(150d, Gather.sumAsDouble(workers, "age")); 68 | 69 | Assert.assertEquals(32l, Gather.minAsLong(workers, "age")); 70 | Assert.assertEquals(32d, Gather.minAsDouble(workers, "age")); 71 | 72 | Assert.assertEquals(46l, Gather.maxAsLong(workers, "age")); 73 | Assert.assertEquals(46d, Gather.maxAsDouble(workers, "age")); 74 | 75 | Assert.assertEquals(37l, Gather.averageAsLong(workers, "age")); 76 | Assert.assertEquals(37.5d, Gather.averageAsDouble(workers, "age")); 77 | 78 | Assert.assertEquals(4, Gather.count(workers, "age")); 79 | 80 | Assert.assertEquals(3, Gather.unique(workers, "age").size()); 81 | Assert.assertEquals(2, Gather.unique(workers, "active").size()); 82 | Assert.assertEquals(3, Gather.unique(workers, "salary").size()); 83 | 84 | // on array next 85 | aggregator = new GatherAggregator.CountingAggregator(); 86 | Gather.aggregate(arrayOfWorkers, "age", aggregator); 87 | Assert.assertEquals(4, aggregator.getResult(0)); 88 | 89 | Assert.assertEquals(150l, Gather.sumAsLong(arrayOfWorkers, "age")); 90 | Assert.assertEquals(150d, Gather.sumAsDouble(arrayOfWorkers, "age")); 91 | 92 | Assert.assertEquals(32l, Gather.minAsLong(arrayOfWorkers, "age")); 93 | Assert.assertEquals(32d, Gather.minAsDouble(arrayOfWorkers, "age")); 94 | 95 | Assert.assertEquals(46l, Gather.maxAsLong(arrayOfWorkers, "age")); 96 | Assert.assertEquals(46d, Gather.maxAsDouble(arrayOfWorkers, "age")); 97 | 98 | Assert.assertEquals(37l, Gather.averageAsLong(arrayOfWorkers, "age")); 99 | Assert.assertEquals(37.5d, Gather.averageAsDouble(arrayOfWorkers, "age")); 100 | 101 | Assert.assertEquals(4, Gather.count(arrayOfWorkers, "age")); 102 | 103 | Assert.assertEquals(3, Gather.unique(arrayOfWorkers, "age").size()); 104 | Assert.assertEquals(2, Gather.unique(arrayOfWorkers, "active").size()); 105 | Assert.assertEquals(3, Gather.unique(arrayOfWorkers, "salary").size()); 106 | } 107 | 108 | @Test 109 | public void testGather() { 110 | final List workers = getWorkers(); 111 | 112 | Gather query = Gather.where("name").is("sandeep"); 113 | 114 | Assert.assertEquals(0, query.count((Object[]) null)); 115 | Assert.assertEquals(0, query.count(new ArrayList<>())); 116 | Assert.assertEquals(0, query.count(workers)); 117 | 118 | Assert.assertEquals(0, query.find(null).size()); 119 | Assert.assertEquals(0, query.find(new ArrayList<>()).size()); 120 | 121 | testGatherQuery(0, Gather.where("noAttribute").existsProperty()); 122 | testGatherQuery(4, Gather.where("noAttribute").notExistsProperty()); 123 | 124 | testGatherQuery(0, Gather.where("name").is("sandeep gupta")); 125 | testGatherQuery(1, Gather.where("name").isIgnoreCase("sandeep gupta")); 126 | 127 | testGatherQuery(0, Gather.where("name").like("*gupta")); 128 | testGatherQuery(2, Gather.where("name").like("S*Gupta")); 129 | testGatherQuery(2, Gather.where("name").not().like("S*Gupta")); 130 | 131 | testGatherQuery(1, query.and("active").is(true)); 132 | testGatherQuery(1, Gather.where("name").like("S*Gupta").and("active").is(false)); 133 | 134 | testGatherQuery(3, Gather.where("salary").greaterThan(40l)); 135 | testGatherQuery(1, Gather.where("salary").greaterThan(50l)); 136 | testGatherQuery(3, Gather.where("salary").greaterThanOrEquals(50l)); 137 | testGatherQuery(1, Gather.where("salary").greaterThanOrEquals(50l).and("active").is(true)); 138 | testGatherQuery(2, Gather.where("salary").greaterThanOrEquals(50l).and("active").is(false)); 139 | 140 | testGatherQuery(4, Gather.where("salary").greaterThan(10l)); 141 | testGatherQuery(0, Gather.where("salary").greaterThan(100l)); 142 | testGatherQuery(1, Gather.where("salary").lessThan(50l)); 143 | testGatherQuery(3, Gather.where("salary").lessThanOrEquals(50l)); 144 | 145 | testGatherQuery(0, Gather.where("salary").regex("S*g")); 146 | testGatherQuery(0, Gather.where("salary").regex(Pattern.compile("S*g"))); 147 | testGatherQuery(4, Gather.where("salary").not().regex("S*g")); 148 | 149 | testGatherQuery(0, Gather.where("name").isNull()); 150 | testGatherQuery(4, Gather.where("name").not().isNull()); 151 | testGatherQuery(4, Gather.where("name").isNotNull()); 152 | 153 | testGatherQuery(4, Gather.hasProperty("name")); 154 | testGatherQuery(0, Gather.hasProperty("sex")); 155 | 156 | testGatherQuery(0, Gather.where("sex").is(Gender.Male)); 157 | 158 | testGatherQuery(3, Gather.where("salary").in(new Object[] { 40l, 50l})); 159 | testGatherQuery(3, Gather.where("salary").in(Arrays.asList(new Object[] { 40l, 50l}))); 160 | 161 | testGatherQuery(2, Gather.where("age").is(32).or("age").is(46)); 162 | } 163 | 164 | @Test 165 | public void testGatherCollections() { 166 | testGatherQuery(2, Gather.where("list").has(36)); 167 | testGatherQuery(2, Gather.where("list").has(true)); 168 | testGatherQuery(2, Gather.where("list").has(50)); 169 | testGatherQuery(1, Gather.where("list").has(40)); 170 | 171 | testGatherQuery(0, Gather.where("list").hasAll(new Integer[] { 40, 60 })); 172 | testGatherQuery(1, Gather.where("list").hasAny(new Integer[] { 40, 60 })); 173 | 174 | testGatherQuery(0, Gather.where("list").hasAll(Arrays.asList(new Integer[] { 40, 60 }))); 175 | testGatherQuery(1, Gather.where("list").hasAny(Arrays.asList(new Integer[] { 40, 60 }))); 176 | } 177 | 178 | @Test 179 | public void testGatherArrays() { 180 | testGatherQuery(2, Gather.where("array").has(36)); 181 | testGatherQuery(2, Gather.where("array").has(true)); 182 | testGatherQuery(2, Gather.where("array").has(50)); 183 | testGatherQuery(1, Gather.where("array").has(40)); 184 | 185 | testGatherQuery(0, Gather.where("array").hasAll(new Integer[] { 40, 60 })); 186 | testGatherQuery(1, Gather.where("array").hasAny(new Integer[] { 40, 60 })); 187 | 188 | testGatherQuery(0, Gather.where("array").hasAll(Arrays.asList(new Integer[] { 40, 60 }))); 189 | testGatherQuery(1, Gather.where("array").hasAny(Arrays.asList(new Integer[] { 40, 60 }))); 190 | } 191 | 192 | @Test 193 | public void testQueryBuilderErrors() { 194 | try { Gather.where("name").and("age"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 195 | try { Gather.where("name").or("age"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 196 | try { Gather.where("name").is("sandeep").not(); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 197 | try { Gather.where("name").is("sandeep").is("gupta"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 198 | try { Gather.where("name").is("sandeep").isNull(); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 199 | try { Gather.where("name").is("sandeep").isNotNull(); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 200 | try { Gather.where("name").is("sandeep").isIgnoreCase("gupta"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 201 | try { Gather.where("name").is("sandeep").like("gupta"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 202 | try { Gather.where("name").is("sandeep").regex("gupta"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 203 | try { Gather.where("name").is("sandeep").regex(Pattern.compile("gupta")); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 204 | 205 | try { Gather.where("age").is("36").greaterThan(40); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 206 | try { Gather.where("age").is("36").greaterThanOrEquals(40); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 207 | try { Gather.where("age").is("36").lessThan(40); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 208 | try { Gather.where("age").is("36").lessThanOrEquals(40); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 209 | 210 | try { Gather.where("age").is("36").in(new Object[] { 40 }); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 211 | try { Gather.where("age").is("36").in(new ArrayList<>()); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 212 | } 213 | 214 | @Test 215 | public void testQueryExecutionErrors() { 216 | try { Gather.sumAsLong(getWorkers(), "name"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 217 | try { Gather.sumAsDouble(getWorkers(), "name"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 218 | 219 | try { Gather.maxAsLong(getWorkers(), "name"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 220 | try { Gather.maxAsDouble(getWorkers(), "name"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 221 | 222 | try { Gather.minAsLong(getWorkers(), "name"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 223 | try { Gather.minAsDouble(getWorkers(), "name"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 224 | 225 | try { Gather.averageAsLong(getWorkers(), "name"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 226 | try { Gather.averageAsDouble(getWorkers(), "name"); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 227 | } 228 | 229 | private boolean testGatherQuery(int expected, Gather query) { 230 | List result = query.find(this.getWorkers()); 231 | if(expected == 0) { 232 | if(result == null || result.size() == 0) { 233 | return true; 234 | } 235 | 236 | return false; 237 | } 238 | 239 | if(expected != result.size()) { 240 | return false; 241 | } 242 | 243 | return expected == query.count(this.getWorkers()); 244 | } 245 | 246 | private static List getWorkers() { 247 | List workers = new ArrayList<>(); 248 | 249 | workers.add(new Worker("Sandeep Gupta", 36, true, 40l)); 250 | workers.add(new Worker("Abhishek Gupta", 32, true, 50l)); 251 | workers.add(new Worker("Amit Modi", 36, false, 50l)); 252 | workers.add(new Worker("Sushant Gupta", 46, false, 70l)); 253 | 254 | return workers; 255 | } 256 | 257 | static class Worker { 258 | 259 | String name; 260 | 261 | int age; 262 | 263 | boolean active; 264 | 265 | long salary; 266 | 267 | List list = new ArrayList<>(); 268 | 269 | Object[] array; 270 | 271 | @Override 272 | public String toString() { 273 | return this.name + ", age=" + this.age + ", active=" + this.active + ", salary=" + this.salary; 274 | } 275 | 276 | public Worker(String name, int age, boolean active, long salary) { 277 | this.name = name; 278 | this.age = age; 279 | this.active = active; 280 | this.salary = salary; 281 | 282 | this.list.add(name); 283 | this.list.add(String.valueOf(age)); 284 | this.list.add(String.valueOf(salary)); 285 | this.list.add(String.valueOf(active)); 286 | 287 | this.array = this.list.toArray(new Object[] {}); 288 | } 289 | 290 | } 291 | 292 | static enum Gender { 293 | 294 | Male, 295 | 296 | Female; 297 | } 298 | 299 | } 300 | -------------------------------------------------------------------------------- /src/test/java/com/sangupta/gather/TestGatherAggregator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | import java.util.Random; 25 | 26 | import org.junit.Assert; 27 | import org.junit.Test; 28 | 29 | import com.sangupta.gather.GatherAggregator.CountingAggregator; 30 | import com.sangupta.gather.GatherAggregator.DoubleAverageAggregator; 31 | import com.sangupta.gather.GatherAggregator.DoubleMaxAggregator; 32 | import com.sangupta.gather.GatherAggregator.DoubleMinAggregator; 33 | import com.sangupta.gather.GatherAggregator.DoubleSumAggregator; 34 | import com.sangupta.gather.GatherAggregator.LongAverageAggregator; 35 | import com.sangupta.gather.GatherAggregator.LongMaxAggregator; 36 | import com.sangupta.gather.GatherAggregator.LongMinAggregator; 37 | import com.sangupta.gather.GatherAggregator.LongSumAggregator; 38 | import com.sangupta.gather.GatherAggregator.UniqueAggregator; 39 | 40 | public class TestGatherAggregator { 41 | 42 | @Test 43 | public void testUniqueAggregator() { 44 | UniqueAggregator aggregator = new UniqueAggregator(); 45 | 46 | Object instance = new Object(); 47 | Assert.assertEquals(0, aggregator.getResult(0)); 48 | Assert.assertEquals(0, aggregator.getUniqueSet().size()); 49 | 50 | aggregator.aggregate(0, instance); 51 | Assert.assertEquals(1, aggregator.getResult(0)); 52 | Assert.assertEquals(1, aggregator.getUniqueSet().size()); 53 | 54 | aggregator.aggregate(0, instance); 55 | aggregator.aggregate(0, instance); 56 | aggregator.aggregate(0, instance); 57 | Assert.assertEquals(1, aggregator.getResult(0)); 58 | Assert.assertEquals(1, aggregator.getUniqueSet().size()); 59 | 60 | aggregator.aggregate(0, new Object()); 61 | Assert.assertEquals(2, aggregator.getResult(0)); 62 | Assert.assertEquals(2, aggregator.getUniqueSet().size()); 63 | 64 | aggregator.aggregate(0, new Object()); 65 | aggregator.aggregate(0, null); 66 | aggregator.aggregate(0, new Object()); 67 | aggregator.aggregate(0, null); 68 | aggregator.aggregate(0, new Object()); 69 | aggregator.aggregate(0, null); 70 | Assert.assertEquals(5, aggregator.getResult(0)); 71 | Assert.assertEquals(5, aggregator.getUniqueSet().size()); 72 | } 73 | 74 | @Test 75 | public void testCountingAggregator() { 76 | CountingAggregator aggregator = new CountingAggregator(); 77 | 78 | Assert.assertEquals(0, aggregator.getResult(0)); 79 | 80 | aggregator.aggregate(0, null); 81 | Assert.assertEquals(1, aggregator.getResult(0)); 82 | 83 | aggregator.aggregate(0, null); 84 | aggregator.aggregate(0, null); 85 | aggregator.aggregate(0, null); 86 | Assert.assertEquals(4, aggregator.getResult(0)); 87 | } 88 | 89 | @Test 90 | public void testDoubleMinAggregator() { 91 | DoubleMinAggregator aggregator = new DoubleMinAggregator(); 92 | 93 | Random random = new Random(); 94 | double result = Double.MAX_VALUE; 95 | for(int index = 0; index < 100000; index++) { 96 | double value = random.nextDouble(); 97 | if(result > value) { 98 | result = value; 99 | } 100 | 101 | aggregator.aggregate(index, value); 102 | } 103 | 104 | Assert.assertEquals(result, aggregator.getResult(0)); 105 | } 106 | 107 | @Test 108 | public void testDoubleMaxAggregator() { 109 | DoubleMaxAggregator aggregator = new DoubleMaxAggregator(); 110 | 111 | Random random = new Random(); 112 | double result = Double.MIN_VALUE; 113 | for(int index = 0; index < 100000; index++) { 114 | double value = random.nextDouble(); 115 | if(result < value) { 116 | result = value; 117 | } 118 | 119 | aggregator.aggregate(index, value); 120 | } 121 | 122 | Assert.assertEquals(result, aggregator.getResult(0)); 123 | } 124 | 125 | @Test 126 | public void testDoubleSumAggregator() { 127 | DoubleSumAggregator aggregator = new DoubleSumAggregator(); 128 | 129 | Random random = new Random(); 130 | double result = 0; 131 | for(int index = 0; index < 100000; index++) { 132 | double value = random.nextDouble(); 133 | result += value; 134 | 135 | aggregator.aggregate(index, value); 136 | } 137 | 138 | Assert.assertEquals(result, aggregator.getResult(0)); 139 | } 140 | 141 | @Test 142 | public void testDoubleAverageAggregator() { 143 | DoubleAverageAggregator aggregator = new DoubleAverageAggregator(); 144 | 145 | Random random = new Random(); 146 | double result = 0; 147 | int counted = 0; 148 | for(int index = 0; index < 100000; index++) { 149 | double value = random.nextDouble(); 150 | result += value; 151 | counted++; 152 | 153 | aggregator.aggregate(index, value); 154 | } 155 | 156 | Assert.assertEquals(result / counted, aggregator.getResult(counted)); 157 | Assert.assertEquals(0d, new DoubleAverageAggregator().getResult(0)); 158 | } 159 | 160 | @Test 161 | public void testLongMinAggregator() { 162 | LongMinAggregator aggregator = new LongMinAggregator(); 163 | 164 | Random random = new Random(); 165 | long result = Long.MAX_VALUE; 166 | for(int index = 0; index < 100000; index++) { 167 | long value = random.nextLong(); 168 | if(result > value) { 169 | result = value; 170 | } 171 | 172 | aggregator.aggregate(index, value); 173 | } 174 | 175 | Assert.assertEquals(result, aggregator.getResult(0)); 176 | } 177 | 178 | @Test 179 | public void testLongMaxAggregator() { 180 | LongMaxAggregator aggregator = new LongMaxAggregator(); 181 | 182 | Random random = new Random(); 183 | long result = Long.MIN_VALUE; 184 | for(int index = 0; index < 100000; index++) { 185 | long value = random.nextLong(); 186 | if(result < value) { 187 | result = value; 188 | } 189 | 190 | aggregator.aggregate(index, value); 191 | } 192 | 193 | Assert.assertEquals(result, aggregator.getResult(0)); 194 | } 195 | 196 | @Test 197 | public void testLongSumAggregator() { 198 | LongSumAggregator aggregator = new LongSumAggregator(); 199 | 200 | Random random = new Random(); 201 | long result = 0; 202 | for(int index = 0; index < 100000; index++) { 203 | long value = random.nextLong(); 204 | result += value; 205 | 206 | aggregator.aggregate(index, value); 207 | } 208 | 209 | Assert.assertEquals(result, aggregator.getResult(0)); 210 | } 211 | 212 | @Test 213 | public void testLongAverageAggregator() { 214 | LongAverageAggregator aggregator = new LongAverageAggregator(); 215 | 216 | Random random = new Random(); 217 | long result = 0; 218 | int counted = 0; 219 | for(int index = 0; index < 100000; index++) { 220 | long value = random.nextLong(); 221 | result += value; 222 | counted++; 223 | 224 | aggregator.aggregate(index, value); 225 | } 226 | 227 | Assert.assertEquals(result / counted, aggregator.getResult(counted)); 228 | Assert.assertEquals(0d, new LongAverageAggregator().getResult(0)); 229 | 230 | try { new LongAverageAggregator().aggregate(1, new Object()); Assert.assertTrue(false); } catch(IllegalArgumentException e) { Assert.assertTrue(true); } 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /src/test/java/com/sangupta/gather/TestGatherExecutor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | import java.util.ArrayList; 25 | import java.util.Collection; 26 | import java.util.List; 27 | 28 | import org.junit.Assert; 29 | import org.junit.Test; 30 | 31 | import com.sangupta.gather.GatherAggregator.CountingAggregator; 32 | 33 | /** 34 | * Unit tests for {@link GatherExecutor}. 35 | * 36 | * @author sangupta 37 | * 38 | */ 39 | public class TestGatherExecutor { 40 | 41 | @Test 42 | public void testMatches() { 43 | Assert.assertFalse(GatherExecutor.matches(null, Gather.where("name").is("sangupta"))); 44 | Assert.assertFalse(GatherExecutor.matches(new Object(), null)); 45 | } 46 | 47 | @Test 48 | public void testHandleRegexMatch() { 49 | Assert.assertFalse(GatherExecutor.handleRegexMatch(null, new Object())); 50 | Assert.assertFalse(GatherExecutor.handleRegexMatch(new Object(), null)); 51 | } 52 | 53 | @Test 54 | public void testAggregate() { 55 | Assert.assertNull(GatherExecutor.aggregate((Collection) null, null, null)); 56 | Assert.assertNull(GatherExecutor.aggregate((Object[]) null, null, null)); 57 | 58 | Assert.assertNull(GatherExecutor.aggregate(new ArrayList<>(), null, null)); 59 | Assert.assertNull(GatherExecutor.aggregate(new Object[] {}, null, null)); 60 | 61 | Assert.assertNull(GatherExecutor.aggregate(new ArrayList<>(), "age", null)); 62 | Assert.assertNull(GatherExecutor.aggregate(new Object[] {}, "age", null)); 63 | 64 | Assert.assertNull(GatherExecutor.aggregate(new ArrayList<>(), "age", new CountingAggregator())); 65 | Assert.assertNull(GatherExecutor.aggregate(new Object[] {}, "age", new CountingAggregator())); 66 | } 67 | 68 | @Test 69 | public void testHandleEquals() { 70 | Assert.assertFalse(GatherExecutor.handleEquals(null, null)); 71 | Assert.assertFalse(GatherExecutor.handleEquals(new Object(), null)); 72 | Assert.assertFalse(GatherExecutor.handleEquals(null, new Object())); 73 | 74 | Object instance = new Object(); 75 | Assert.assertFalse(GatherExecutor.handleEquals(instance, new Object())); 76 | Assert.assertTrue(GatherExecutor.handleEquals(instance, instance)); 77 | 78 | Assert.assertTrue(GatherExecutor.handleEquals("hello", "hello")); 79 | Assert.assertTrue(GatherExecutor.handleEquals("hello", new String("hello"))); 80 | Assert.assertTrue(GatherExecutor.handleEquals("hello", "hello".intern())); 81 | 82 | Assert.assertTrue(GatherExecutor.handleEquals(123l, new Long(123))); 83 | Assert.assertTrue(GatherExecutor.handleEquals(123, new Integer(123))); 84 | } 85 | 86 | @Test 87 | public void testHandleEqualsIgnoreCase() { 88 | Assert.assertFalse(GatherExecutor.handleEqualsIgnoreCase(null, null)); 89 | Assert.assertFalse(GatherExecutor.handleEqualsIgnoreCase(new Object(), null)); 90 | Assert.assertFalse(GatherExecutor.handleEqualsIgnoreCase(null, new Object())); 91 | 92 | Object instance = new Object(); 93 | Assert.assertFalse(GatherExecutor.handleEqualsIgnoreCase(instance, new Object())); 94 | Assert.assertTrue(GatherExecutor.handleEqualsIgnoreCase(instance, instance)); 95 | 96 | Assert.assertTrue(GatherExecutor.handleEqualsIgnoreCase("hello", "HELLO")); 97 | Assert.assertTrue(GatherExecutor.handleEqualsIgnoreCase("hello", new String("HELLO"))); 98 | Assert.assertTrue(GatherExecutor.handleEqualsIgnoreCase("hello", "heLLo".intern())); 99 | 100 | Assert.assertTrue(GatherExecutor.handleEqualsIgnoreCase(123l, new Long(123))); 101 | Assert.assertTrue(GatherExecutor.handleEqualsIgnoreCase(123, new Integer(123))); 102 | } 103 | 104 | @Test 105 | public void testHandleNull() { 106 | Assert.assertTrue(GatherExecutor.handleNull(null, new Object())); 107 | Assert.assertFalse(GatherExecutor.handleNull(new Object(), new Object())); 108 | 109 | Assert.assertTrue(GatherExecutor.handleNull(null, null)); 110 | Assert.assertFalse(GatherExecutor.handleNull(new Object(), null)); 111 | } 112 | 113 | @Test 114 | public void testHandleValueIn() { 115 | Assert.assertFalse(GatherExecutor.handleValueIn(null, null)); 116 | Assert.assertFalse(GatherExecutor.handleValueIn(new Object(), null)); 117 | 118 | List list = new ArrayList<>(); 119 | Assert.assertFalse(GatherExecutor.handleValueIn(list, null)); 120 | Assert.assertFalse(GatherExecutor.handleValueIn(list, "hello")); 121 | Assert.assertFalse(GatherExecutor.handleValueIn(null, list)); 122 | Assert.assertFalse(GatherExecutor.handleValueIn("hello", list)); 123 | 124 | list.add("hello"); 125 | list.add("world"); 126 | list.add("life"); 127 | list.add("is"); 128 | list.add("sunny"); 129 | Assert.assertFalse(GatherExecutor.handleValueIn("hello world", list)); 130 | Assert.assertTrue(GatherExecutor.handleValueIn("hello", list)); 131 | Assert.assertTrue(GatherExecutor.handleValueIn("world", list)); 132 | Assert.assertTrue(GatherExecutor.handleValueIn("life", list)); 133 | Assert.assertTrue(GatherExecutor.handleValueIn("is", list)); 134 | Assert.assertTrue(GatherExecutor.handleValueIn("sunny", list)); 135 | 136 | Integer[] array = new Integer[] { 2, 3, 5, 7, 9, 11, 13, 17, 19 }; 137 | Assert.assertFalse(GatherExecutor.handleValueIn(0, array)); 138 | Assert.assertFalse(GatherExecutor.handleValueIn(1, array)); 139 | Assert.assertFalse(GatherExecutor.handleValueIn(4, array)); 140 | 141 | Assert.assertTrue(GatherExecutor.handleValueIn(2, array)); 142 | Assert.assertTrue(GatherExecutor.handleValueIn(13, array)); 143 | Assert.assertTrue(GatherExecutor.handleValueIn(19, array)); 144 | } 145 | 146 | @Test 147 | public void testHandleCollectionHasValue() { 148 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(null, null)); 149 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new Object(), null)); 150 | 151 | List list = new ArrayList<>(); 152 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(list, null)); 153 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(list, "hello")); 154 | 155 | list.add("hello"); 156 | list.add("world"); 157 | list.add("life"); 158 | list.add("is"); 159 | list.add("sunny"); 160 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(list, "hello world")); 161 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(list, "hello")); 162 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(list, "world")); 163 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(list, "life")); 164 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(list, "is")); 165 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(list, "sunny")); 166 | 167 | // object array 168 | 169 | Integer[] array = new Integer[] { 2, 3, 5, 7, 9, 11, 13, 17, 19 }; 170 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(array, 0)); 171 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(array, 1)); 172 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(array, 4)); 173 | 174 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(array, 2)); 175 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(array, 13)); 176 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(array, 19)); 177 | 178 | // char array 179 | 180 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new char[] { 'a', 'b', 'c' }, 'a')); 181 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new char[] { 'a', 'b', 'c' }, 'b')); 182 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new char[] { 'a', 'b', 'c' }, 'c')); 183 | 184 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new char[] { 'a', 'b', 'c' }, 'A')); 185 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new char[] { 'a', 'b', 'c' }, 'B')); 186 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new char[] { 'a', 'b', 'c' }, 'C')); 187 | 188 | // boolean array 189 | 190 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new boolean[] { false, false }, false)); 191 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new boolean[] { false, false }, true)); 192 | 193 | // byte array 194 | 195 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new byte[] { 12, 14 }, 12)); 196 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new byte[] { 12, 14 }, 14)); 197 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new byte[] { 12, 14 }, 11)); 198 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new byte[] { 12, 14 }, 13)); 199 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new byte[] { 12, 14 }, 15)); 200 | 201 | // short array 202 | 203 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new short[] { 12, 14 }, 12)); 204 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new short[] { 12, 14 }, 14)); 205 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new short[] { 12, 14 }, 11)); 206 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new short[] { 12, 14 }, 13)); 207 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new short[] { 12, 14 }, 15)); 208 | 209 | // int array 210 | 211 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new int[] { 12, 14 }, 12)); 212 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new int[] { 12, 14 }, 14)); 213 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new int[] { 12, 14 }, 11)); 214 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new int[] { 12, 14 }, 13)); 215 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new int[] { 12, 14 }, 15)); 216 | 217 | // long array 218 | 219 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new long[] { 12, 14 }, 12)); 220 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new long[] { 12, 14 }, 14)); 221 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new long[] { 12, 14 }, 11)); 222 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new long[] { 12, 14 }, 13)); 223 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new long[] { 12, 14 }, 15)); 224 | 225 | // float array 226 | 227 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new float[] { 12, 14 }, 12)); 228 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new float[] { 12, 14 }, 14)); 229 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new float[] { 12, 14 }, 11)); 230 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new float[] { 12, 14 }, 13)); 231 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new float[] { 12, 14 }, 15)); 232 | 233 | // double array 234 | 235 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new double[] { 12, 14 }, 12)); 236 | Assert.assertTrue(GatherExecutor.handleCollectionHasValue(new double[] { 12, 14 }, 14)); 237 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new double[] { 12, 14 }, 11)); 238 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new double[] { 12, 14 }, 13)); 239 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new double[] { 12, 14 }, 15)); 240 | 241 | // unknown 242 | 243 | Assert.assertFalse(GatherExecutor.handleCollectionHasValue(new double[] { 12, 14 }, true)); 244 | } 245 | 246 | @Test 247 | public void testHandleWildcardMatch() { 248 | Assert.assertFalse(GatherExecutor.handleWildcardMatch(null, null)); 249 | Assert.assertFalse(GatherExecutor.handleWildcardMatch(null, "*")); 250 | Assert.assertFalse(GatherExecutor.handleWildcardMatch("abc", null)); 251 | 252 | Assert.assertFalse(GatherExecutor.handleWildcardMatch("one more", "")); 253 | 254 | Assert.assertTrue(GatherExecutor.handleWildcardMatch("abc.wav", "*")); 255 | Assert.assertTrue(GatherExecutor.handleWildcardMatch("abc.wav", "*.w?v")); 256 | Assert.assertTrue(GatherExecutor.handleWildcardMatch("abc.wav", "*b?.wav")); 257 | Assert.assertTrue(GatherExecutor.handleWildcardMatch("abc.wav", "*.wav")); 258 | Assert.assertTrue(GatherExecutor.handleWildcardMatch("abc.wav", "*abc.wav")); 259 | Assert.assertTrue(GatherExecutor.handleWildcardMatch("abc.wav", "???.wav")); 260 | Assert.assertTrue(GatherExecutor.handleWildcardMatch("abc.wav", "???.???")); 261 | Assert.assertTrue(GatherExecutor.handleWildcardMatch("abc.wav", "???.???")); 262 | 263 | Assert.assertFalse(GatherExecutor.handleWildcardMatch("abc.wav", "*.html")); 264 | Assert.assertFalse(GatherExecutor.handleWildcardMatch("abc.wav", "?.wav")); 265 | Assert.assertFalse(GatherExecutor.handleWildcardMatch("abc.wav", "??.wav")); 266 | Assert.assertFalse(GatherExecutor.handleWildcardMatch("abc.wav", "abc.wi?")); 267 | 268 | Assert.assertTrue(GatherExecutor.handleWildcardMatch("http://sangupta.com/tech/page10/index.html", "*tech/page*")); 269 | } 270 | 271 | @Test 272 | public void testHandleCollectionHasAllOrAnyValues() { 273 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(null, null, true)); 274 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(null, null, false)); 275 | 276 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new int[] {}, null, true)); 277 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new int[] {}, null, false)); 278 | 279 | // char array 280 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new char[] { 'a', 'b', 'c' }, new char[] { 'a', 'b' }, true)); 281 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new char[] { 'a', 'b', 'c' }, new char[] { 'a', 'd' }, false)); 282 | 283 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new char[] { 'a', 'b', 'c' }, new char[] { 'a', 'd' }, true)); 284 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new char[] { 'a', 'b', 'c' }, new char[] { 'd', 'e' }, false)); 285 | 286 | // boolean array 287 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new boolean[] { true }, new boolean[] { true, true }, true)); 288 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new boolean[] { true }, new boolean[] { true, false }, false)); 289 | 290 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new boolean[] { true }, new boolean[] { false, false, true }, true)); 291 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new boolean[] { true }, new boolean[] { false, false }, false)); 292 | 293 | // byte array 294 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new byte[] { 2, 4, 8, 16 }, new byte[] { 4, 8, 16 }, true)); 295 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new byte[] { 2, 4, 8, 16 }, new byte[] { 8, 16, 32 }, false)); 296 | 297 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new byte[] { 2, 4, 8, 16 }, new byte[] { 4, 8, 16, 32 }, true)); 298 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new byte[] { 2, 4, 8, 16 }, new byte[] { 32, 64, 1 }, false)); 299 | 300 | // short array 301 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new short[] { 2, 4, 8, 16 }, new short[] { 4, 8, 16 }, true)); 302 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new short[] { 2, 4, 8, 16 }, new short[] { 8, 16, 32 }, false)); 303 | 304 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new short[] { 2, 4, 8, 16 }, new short[] { 4, 8, 16, 32 }, true)); 305 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new short[] { 2, 4, 8, 16 }, new short[] { 32, 64, 1 }, false)); 306 | 307 | // int array 308 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new int[] { 2, 4, 8, 16 }, new int[] { 4, 8, 16 }, true)); 309 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new int[] { 2, 4, 8, 16 }, new int[] { 8, 16, 32 }, false)); 310 | 311 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new int[] { 2, 4, 8, 16 }, new int[] { 4, 8, 16, 32 }, true)); 312 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new int[] { 2, 4, 8, 16 }, new int[] { 32, 64, 1 }, false)); 313 | 314 | // long array 315 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new long[] { 2, 4, 8, 16 }, new long[] { 4, 8, 16 }, true)); 316 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new long[] { 2, 4, 8, 16 }, new long[] { 8, 16, 32 }, false)); 317 | 318 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new long[] { 2, 4, 8, 16 }, new long[] { 4, 8, 16, 32 }, true)); 319 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new long[] { 2, 4, 8, 16 }, new long[] { 32, 64, 1 }, false)); 320 | 321 | 322 | // float array 323 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new float[] { 2, 4, 8, 16 }, new float[] { 4, 8, 16 }, true)); 324 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new float[] { 2, 4, 8, 16 }, new float[] { 8, 16, 32 }, false)); 325 | 326 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new float[] { 2, 4, 8, 16 }, new float[] { 4, 8, 16, 32 }, true)); 327 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new float[] { 2, 4, 8, 16 }, new float[] { 32, 64, 1 }, false)); 328 | 329 | // double array 330 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new double[] { 2, 4, 8, 16 }, new double[] { 4, 8, 16 }, true)); 331 | Assert.assertTrue(GatherExecutor.handleCollectionHasAllOrAnyValues(new double[] { 2, 4, 8, 16 }, new double[] { 8, 16, 32 }, false)); 332 | 333 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new double[] { 2, 4, 8, 16 }, new double[] { 4, 8, 16, 32 }, true)); 334 | Assert.assertFalse(GatherExecutor.handleCollectionHasAllOrAnyValues(new double[] { 2, 4, 8, 16 }, new double[] { 32, 64, 1 }, false)); 335 | } 336 | 337 | @Test 338 | public void testHandleNumericComparison() { 339 | Assert.assertFalse(GatherExecutor.handleNumericComparison(null, 123, GatherNumericComparison.LESS_THAN)); 340 | Assert.assertFalse(GatherExecutor.handleNumericComparison(123, null, GatherNumericComparison.LESS_THAN)); 341 | 342 | Assert.assertFalse(GatherExecutor.handleNumericComparison(123, new Object(), GatherNumericComparison.LESS_THAN)); 343 | Assert.assertTrue(GatherExecutor.handleNumericComparison('a', 'b', GatherNumericComparison.LESS_THAN)); 344 | Assert.assertFalse(GatherExecutor.handleNumericComparison(new Object(), new Object(), GatherNumericComparison.LESS_THAN)); 345 | } 346 | 347 | } 348 | -------------------------------------------------------------------------------- /src/test/java/com/sangupta/gather/TestGatherPerformance.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | import java.util.Random; 27 | 28 | import org.openjdk.jmh.annotations.Benchmark; 29 | import org.openjdk.jmh.annotations.BenchmarkMode; 30 | import org.openjdk.jmh.annotations.Mode; 31 | import org.openjdk.jmh.runner.Runner; 32 | import org.openjdk.jmh.runner.RunnerException; 33 | import org.openjdk.jmh.runner.options.Options; 34 | import org.openjdk.jmh.runner.options.OptionsBuilder; 35 | 36 | import com.sangupta.gather.TestGather.Worker; 37 | 38 | /** 39 | * Check simple performance for the library. 40 | * 41 | * @author sangupta 42 | * 43 | */ 44 | @BenchmarkMode(Mode.Throughput) 45 | public class TestGatherPerformance { 46 | 47 | static final List workers = new ArrayList<>(); 48 | 49 | static final Gather nameQuery = Gather.where("name").like("san*"); 50 | 51 | static final Gather ageQuery = Gather.where("age").greaterThan(50); 52 | 53 | static { 54 | String[] names = new String[] { "sandeep", "sangupta", "abhishek", "sushant" }; 55 | Random random = new Random(); 56 | 57 | for(int index = 0; index < 1000*1000; index++) { 58 | int nameIndex = random.nextInt(4); 59 | int age = random.nextInt(100); 60 | workers.add(new Worker(names[nameIndex], age, age % 2 == 0, random.nextInt(1000000))); 61 | } 62 | } 63 | 64 | @Benchmark 65 | public void testLikePerformance() { 66 | int count = nameQuery.find(workers).size(); 67 | } 68 | 69 | @Benchmark 70 | public void testNumericPerformance() { 71 | int count = ageQuery.find(workers).size(); 72 | } 73 | 74 | public static void main(String[] args) throws RunnerException { 75 | Options options = new OptionsBuilder().include(TestGatherPerformance.class.getSimpleName()) 76 | .warmupIterations(5) 77 | .measurementIterations(20) 78 | .threads(1) 79 | .forks(1) 80 | .mode(Mode.Throughput) 81 | .build(); 82 | 83 | new Runner(options).run(); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/com/sangupta/gather/TestGatherProfiling.java: -------------------------------------------------------------------------------- 1 | package com.sangupta.gather; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | import com.sangupta.gather.TestGather.Worker; 8 | 9 | public class TestGatherProfiling { 10 | 11 | static final int MAX_TIMES = 5; 12 | 13 | static final int MAX_SIZE = 1000 * 10; //00; 14 | 15 | static final List workers = new ArrayList<>((int) (MAX_SIZE * 1.1)); 16 | 17 | static final Gather nameQuery = Gather.where("name").like("san*"); 18 | 19 | static final Gather ageQuery = Gather.where("age").greaterThan(50); 20 | 21 | static { 22 | String[] names = new String[] { "sandeep", "sangupta", "abhishek", "sushant" }; 23 | Random random = new Random(); 24 | final int namesLength = names.length; 25 | 26 | for(int index = 0; index < MAX_SIZE; index++) { 27 | int nameIndex = random.nextInt(namesLength); 28 | int age = random.nextInt(100); 29 | workers.add(new Worker(names[nameIndex], age, age % 2 == 0, random.nextInt(1000000))); 30 | } 31 | } 32 | 33 | /** 34 | * To run the test with profiling: use the VM arguments: 35 | * 36 | * -agentlib:hprof=cpu=samples for sample profiling 37 | * -agentlib:hprof=cpu=times for complete profiling 38 | * 39 | * @param args 40 | */ 41 | public static void main23(String[] args) { 42 | long start = System.nanoTime(); 43 | for(int index = 0; index < MAX_TIMES; index++) { 44 | GatherExecutor.handleNumericComparison(123, 123, GatherNumericComparison.GREATER_THAN); 45 | } 46 | long end = System.nanoTime(); 47 | System.out.println("Nano: "+ ((end - start) / MAX_TIMES)); 48 | 49 | start = System.nanoTime(); 50 | for(int index = 0; index < MAX_TIMES; index++) { 51 | GatherExecutor.handleNumericComparison(123, 123, GatherNumericComparison.GREATER_THAN); 52 | } 53 | end = System.nanoTime(); 54 | System.out.println("Nano: "+ ((end - start) / MAX_TIMES)); 55 | } 56 | 57 | public static void main(String[] args) { 58 | for(int index = 0; index < MAX_TIMES; index++) { 59 | ageQuery.find(workers).size(); 60 | } 61 | System.out.println("Done"); 62 | } 63 | 64 | private static void randomTests() { 65 | long start, end; 66 | 67 | start = System.nanoTime(); 68 | for(int index = 0; index < MAX_TIMES; index++) { 69 | nameQuery.find(workers).size(); 70 | ageQuery.find(workers).size(); 71 | } 72 | end = System.nanoTime(); 73 | System.out.println("Nano: "+ ((end - start) / MAX_TIMES)); 74 | 75 | char xx; 76 | String s = "hello world"; 77 | start = System.nanoTime(); 78 | for(int first = 0; first < MAX_SIZE; first++) { 79 | xx = s.charAt(4); 80 | } 81 | end = System.nanoTime(); 82 | System.out.println("Nano: "+ (end - start)); 83 | 84 | char[] x = s.toCharArray(); 85 | start = System.nanoTime(); 86 | for(int first = 0; first < MAX_SIZE; first++) { 87 | xx = x[4]; 88 | } 89 | end = System.nanoTime(); 90 | System.out.println("Nano: "+ (end - start)); 91 | 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/test/java/com/sangupta/gather/TestGatherReflect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | import org.junit.Assert; 25 | import org.junit.Test; 26 | 27 | import com.sangupta.gather.GatherReflect.FieldAndInstance; 28 | 29 | public class TestGatherReflect { 30 | 31 | @Test 32 | public void testGetFieldAndInstance() { 33 | Assert.assertNull(GatherReflect.getFieldAndInstance(null, "hello")); 34 | Assert.assertNull(GatherReflect.getFieldAndInstance(new Object(), null)); 35 | Assert.assertNull(GatherReflect.getFieldAndInstance(new TestClassB(), "tc.ta.tc.age")); 36 | } 37 | 38 | @Test 39 | public void testGetField() { 40 | Assert.assertNull(GatherReflect.getField(null, "intField")); 41 | Assert.assertNull(GatherReflect.getField(null, null)); 42 | Assert.assertNull(GatherReflect.getField(null, "")); 43 | 44 | Assert.assertNull(GatherReflect.getField(new Object(), "intField")); 45 | Assert.assertNull(GatherReflect.getField(new Object(), null)); 46 | Assert.assertNull(GatherReflect.getField(new Object(), "")); 47 | 48 | Assert.assertNotNull(GatherReflect.getField(new TestClassA(), "intField")); 49 | Assert.assertNull(GatherReflect.getField(new TestClassA(), "longField")); 50 | 51 | Assert.assertNotNull(GatherReflect.getField(new TestClassB(), "intField")); 52 | Assert.assertNotNull(GatherReflect.getField(new TestClassB(), "longField")); 53 | } 54 | 55 | @Test 56 | public void testGetAllFields() { 57 | Assert.assertNull(GatherReflect.getAllFields(null)); 58 | } 59 | 60 | @Test(expected = IllegalArgumentException.class) 61 | public void testPopulateAllFields() { 62 | GatherReflect.populateAllFields(null, null); 63 | GatherReflect.populateAllFields(Object.class, null); 64 | } 65 | 66 | @Test 67 | public void testCompositeKey() throws IllegalArgumentException, IllegalAccessException { 68 | FieldAndInstance fi = GatherReflect.getFieldAndInstance(new TestClassB(), "tc.ta.td.age"); 69 | Assert.assertNotNull(fi); 70 | Assert.assertNotNull(fi.field); 71 | Assert.assertNotNull(fi.instance); 72 | 73 | fi.field.setAccessible(true); 74 | 75 | Object value = fi.field.get(fi.instance); 76 | Assert.assertEquals(53, value); 77 | } 78 | 79 | private static class TestClassA { 80 | 81 | private int intField; 82 | 83 | private TestClassD td = new TestClassD(); 84 | 85 | } 86 | 87 | private static class TestClassB extends TestClassA { 88 | 89 | private int longField; 90 | 91 | private TestClassC tc = new TestClassC(); 92 | 93 | } 94 | 95 | private static class TestClassC { 96 | 97 | private int size = 10; 98 | 99 | private TestClassA ta = new TestClassA(); 100 | 101 | } 102 | 103 | private static class TestClassD { 104 | 105 | private int age = 53; 106 | 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/test/java/com/sangupta/gather/TestGatherUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * gather: SQL queries for Java collections 4 | * Copyright (c) 2017, Sandeep Gupta 5 | * 6 | * https://sangupta.com/projects/gather 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | */ 21 | 22 | package com.sangupta.gather; 23 | 24 | import java.math.BigDecimal; 25 | import java.util.ArrayList; 26 | import java.util.Arrays; 27 | import java.util.List; 28 | import java.util.concurrent.atomic.AtomicInteger; 29 | import java.util.concurrent.atomic.AtomicLong; 30 | import java.util.regex.Pattern; 31 | 32 | import org.junit.Assert; 33 | import org.junit.Test; 34 | 35 | /** 36 | * Unit tests for {@link GatherUtils} class. 37 | * 38 | * @author sangupta 39 | * 40 | */ 41 | public class TestGatherUtils { 42 | 43 | @Test 44 | public void testContainsCharArray() { 45 | Assert.assertFalse(GatherUtils.contains((char[]) null, null)); 46 | Assert.assertFalse(GatherUtils.contains((char[]) null, new Object())); 47 | Assert.assertFalse(GatherUtils.contains(new char[] {}, null)); 48 | Assert.assertFalse(GatherUtils.contains(new char[] {}, new Object())); 49 | 50 | Assert.assertTrue(GatherUtils.contains(new char[] { 'a', 'b', 'c' }, 'a')); 51 | Assert.assertTrue(GatherUtils.contains(new char[] { 'a', 'b', 'c' }, 'b')); 52 | Assert.assertTrue(GatherUtils.contains(new char[] { 'a', 'b', 'c' }, 'c')); 53 | Assert.assertFalse(GatherUtils.contains(new char[] { 'a', 'b', 'c' }, 'x')); 54 | Assert.assertFalse(GatherUtils.contains(new char[] { 'a', 'b', 'c' }, 'y')); 55 | Assert.assertFalse(GatherUtils.contains(new char[] { 'a', 'b', 'c' }, 'z')); 56 | Assert.assertTrue(GatherUtils.contains(new char[] { 'a', 'b', 'c' }, new Character('a'))); 57 | Assert.assertFalse(GatherUtils.contains(new char[] { 'a', 'b', 'c' }, new Character('x'))); 58 | } 59 | 60 | @Test 61 | public void testContainsBooleanArray() { 62 | Assert.assertFalse(GatherUtils.contains((boolean[]) null, null)); 63 | Assert.assertFalse(GatherUtils.contains((boolean[]) null, new Object())); 64 | Assert.assertFalse(GatherUtils.contains(new boolean[] {}, null)); 65 | Assert.assertFalse(GatherUtils.contains(new boolean[] {}, new Object())); 66 | 67 | Assert.assertFalse(GatherUtils.contains(new boolean[] {}, true)); 68 | Assert.assertFalse(GatherUtils.contains(new boolean[] {}, false)); 69 | Assert.assertTrue(GatherUtils.contains(new boolean[] { true }, true)); 70 | Assert.assertFalse(GatherUtils.contains(new boolean[] { true }, false)); 71 | Assert.assertTrue(GatherUtils.contains(new boolean[] { false }, false)); 72 | Assert.assertFalse(GatherUtils.contains(new boolean[] { false }, true)); 73 | } 74 | 75 | @Test 76 | public void testContainsByteArray() { 77 | Assert.assertFalse(GatherUtils.contains((byte[]) null, (Object) null)); 78 | 79 | Assert.assertFalse(GatherUtils.contains((byte[]) null, null)); 80 | Assert.assertFalse(GatherUtils.contains((byte[]) null, new Object())); 81 | Assert.assertFalse(GatherUtils.contains(new byte[] {}, null)); 82 | Assert.assertFalse(GatherUtils.contains(new byte[] {}, new Object())); 83 | 84 | Assert.assertFalse(GatherUtils.contains(new byte[] { 2, 4, 8, 16, 32 }, 1)); 85 | Assert.assertFalse(GatherUtils.contains(new byte[] { 2, 4, 8, 16, 32 }, 3)); 86 | Assert.assertFalse(GatherUtils.contains(new byte[] { 2, 4, 8, 16, 32 }, 9)); 87 | Assert.assertFalse(GatherUtils.contains(new byte[] { 2, 4, 8, 16, 32 }, 27)); 88 | 89 | Assert.assertTrue(GatherUtils.contains(new byte[] { 2, 4, 8, 16, 32 }, 2)); 90 | Assert.assertTrue(GatherUtils.contains(new byte[] { 2, 4, 8, 16, 32 }, 4)); 91 | Assert.assertTrue(GatherUtils.contains(new byte[] { 2, 4, 8, 16, 32 }, 8)); 92 | Assert.assertTrue(GatherUtils.contains(new byte[] { 2, 4, 8, 16, 32 }, 16)); 93 | Assert.assertTrue(GatherUtils.contains(new byte[] { 2, 4, 8, 16, 32 }, 32)); 94 | } 95 | 96 | @Test 97 | public void testContainsShortArray() { 98 | Assert.assertFalse(GatherUtils.contains((short[]) null, (Object) null)); 99 | 100 | Assert.assertFalse(GatherUtils.contains((short[]) null, null)); 101 | Assert.assertFalse(GatherUtils.contains((short[]) null, new Object())); 102 | Assert.assertFalse(GatherUtils.contains(new short[] {}, null)); 103 | Assert.assertFalse(GatherUtils.contains(new short[] {}, new Object())); 104 | 105 | Assert.assertFalse(GatherUtils.contains(new short[] { 2, 4, 8, 16, 32 }, 1)); 106 | Assert.assertFalse(GatherUtils.contains(new short[] { 2, 4, 8, 16, 32 }, 3)); 107 | Assert.assertFalse(GatherUtils.contains(new short[] { 2, 4, 8, 16, 32 }, 9)); 108 | Assert.assertFalse(GatherUtils.contains(new short[] { 2, 4, 8, 16, 32 }, 27)); 109 | 110 | Assert.assertTrue(GatherUtils.contains(new short[] { 2, 4, 8, 16, 32 }, 2)); 111 | Assert.assertTrue(GatherUtils.contains(new short[] { 2, 4, 8, 16, 32 }, 4)); 112 | Assert.assertTrue(GatherUtils.contains(new short[] { 2, 4, 8, 16, 32 }, 8)); 113 | Assert.assertTrue(GatherUtils.contains(new short[] { 2, 4, 8, 16, 32 }, 16)); 114 | Assert.assertTrue(GatherUtils.contains(new short[] { 2, 4, 8, 16, 32 }, 32)); 115 | } 116 | 117 | @Test 118 | public void testContainsIntegerArray() { 119 | Assert.assertFalse(GatherUtils.contains((int[]) null, (Object) null)); 120 | 121 | Assert.assertFalse(GatherUtils.contains((int[]) null, null)); 122 | Assert.assertFalse(GatherUtils.contains((int[]) null, new Object())); 123 | Assert.assertFalse(GatherUtils.contains(new int[] {}, null)); 124 | Assert.assertFalse(GatherUtils.contains(new int[] {}, new Object())); 125 | 126 | Assert.assertFalse(GatherUtils.contains(new int[] { 2, 4, 8, 16, 32 }, 1)); 127 | Assert.assertFalse(GatherUtils.contains(new int[] { 2, 4, 8, 16, 32 }, 3)); 128 | Assert.assertFalse(GatherUtils.contains(new int[] { 2, 4, 8, 16, 32 }, 9)); 129 | Assert.assertFalse(GatherUtils.contains(new int[] { 2, 4, 8, 16, 32 }, 27)); 130 | 131 | Assert.assertTrue(GatherUtils.contains(new int[] { 2, 4, 8, 16, 32 }, 2)); 132 | Assert.assertTrue(GatherUtils.contains(new int[] { 2, 4, 8, 16, 32 }, 4)); 133 | Assert.assertTrue(GatherUtils.contains(new int[] { 2, 4, 8, 16, 32 }, 8)); 134 | Assert.assertTrue(GatherUtils.contains(new int[] { 2, 4, 8, 16, 32 }, 16)); 135 | Assert.assertTrue(GatherUtils.contains(new int[] { 2, 4, 8, 16, 32 }, 32)); 136 | } 137 | 138 | @Test 139 | public void testContainsLongArray() { 140 | Assert.assertFalse(GatherUtils.contains((long[]) null, (Object) null)); 141 | 142 | Assert.assertFalse(GatherUtils.contains((long[]) null, null)); 143 | Assert.assertFalse(GatherUtils.contains((long[]) null, new Object())); 144 | Assert.assertFalse(GatherUtils.contains(new long[] {}, null)); 145 | Assert.assertFalse(GatherUtils.contains(new long[] {}, new Object())); 146 | 147 | Assert.assertFalse(GatherUtils.contains(new long[] { 2, 4, 8, 16, 32 }, 1)); 148 | Assert.assertFalse(GatherUtils.contains(new long[] { 2, 4, 8, 16, 32 }, 3)); 149 | Assert.assertFalse(GatherUtils.contains(new long[] { 2, 4, 8, 16, 32 }, 9)); 150 | Assert.assertFalse(GatherUtils.contains(new long[] { 2, 4, 8, 16, 32 }, 27)); 151 | 152 | Assert.assertTrue(GatherUtils.contains(new long[] { 2, 4, 8, 16, 32 }, 2)); 153 | Assert.assertTrue(GatherUtils.contains(new long[] { 2, 4, 8, 16, 32 }, 4)); 154 | Assert.assertTrue(GatherUtils.contains(new long[] { 2, 4, 8, 16, 32 }, 8)); 155 | Assert.assertTrue(GatherUtils.contains(new long[] { 2, 4, 8, 16, 32 }, 16)); 156 | Assert.assertTrue(GatherUtils.contains(new long[] { 2, 4, 8, 16, 32 }, 32)); 157 | } 158 | 159 | @Test 160 | public void testContainsFloatArray() { 161 | Assert.assertFalse(GatherUtils.contains((float[]) null, (Object) null)); 162 | 163 | Assert.assertFalse(GatherUtils.contains((float[]) null, null)); 164 | Assert.assertFalse(GatherUtils.contains((float[]) null, new Object())); 165 | Assert.assertFalse(GatherUtils.contains(new float[] {}, null)); 166 | Assert.assertFalse(GatherUtils.contains(new float[] {}, new Object())); 167 | 168 | Assert.assertFalse(GatherUtils.contains(new float[] { 2, 4, 8, 16, 32 }, 1)); 169 | Assert.assertFalse(GatherUtils.contains(new float[] { 2, 4, 8, 16, 32 }, 3)); 170 | Assert.assertFalse(GatherUtils.contains(new float[] { 2, 4, 8, 16, 32 }, 9)); 171 | Assert.assertFalse(GatherUtils.contains(new float[] { 2, 4, 8, 16, 32 }, 27)); 172 | 173 | Assert.assertTrue(GatherUtils.contains(new float[] { 2, 4, 8, 16, 32 }, 2)); 174 | Assert.assertTrue(GatherUtils.contains(new float[] { 2, 4, 8, 16, 32 }, 4)); 175 | Assert.assertTrue(GatherUtils.contains(new float[] { 2, 4, 8, 16, 32 }, 8)); 176 | Assert.assertTrue(GatherUtils.contains(new float[] { 2, 4, 8, 16, 32 }, 16)); 177 | Assert.assertTrue(GatherUtils.contains(new float[] { 2, 4, 8, 16, 32 }, 32)); 178 | } 179 | 180 | @Test 181 | public void testContainsDoubleArray() { 182 | Assert.assertFalse(GatherUtils.contains((double[]) null, (Object) null)); 183 | 184 | Assert.assertFalse(GatherUtils.contains((double[]) null, null)); 185 | Assert.assertFalse(GatherUtils.contains((double[]) null, new Object())); 186 | Assert.assertFalse(GatherUtils.contains(new double[] {}, null)); 187 | Assert.assertFalse(GatherUtils.contains(new double[] {}, new Object())); 188 | 189 | Assert.assertFalse(GatherUtils.contains(new double[] { 2, 4, 8, 16, 32 }, 1)); 190 | Assert.assertFalse(GatherUtils.contains(new double[] { 2, 4, 8, 16, 32 }, 3)); 191 | Assert.assertFalse(GatherUtils.contains(new double[] { 2, 4, 8, 16, 32 }, 9)); 192 | Assert.assertFalse(GatherUtils.contains(new double[] { 2, 4, 8, 16, 32 }, 27)); 193 | 194 | Assert.assertTrue(GatherUtils.contains(new double[] { 2, 4, 8, 16, 32 }, 2)); 195 | Assert.assertTrue(GatherUtils.contains(new double[] { 2, 4, 8, 16, 32 }, 4)); 196 | Assert.assertTrue(GatherUtils.contains(new double[] { 2, 4, 8, 16, 32 }, 8)); 197 | Assert.assertTrue(GatherUtils.contains(new double[] { 2, 4, 8, 16, 32 }, 16)); 198 | Assert.assertTrue(GatherUtils.contains(new double[] { 2, 4, 8, 16, 32 }, 32)); 199 | } 200 | 201 | @Test 202 | public void testContainsObjectArray() { 203 | Assert.assertFalse(GatherUtils.contains((Object[]) null, null)); 204 | Assert.assertFalse(GatherUtils.contains((Object[]) null, new Object())); 205 | Assert.assertFalse(GatherUtils.contains(new Object[] {}, null)); 206 | Assert.assertFalse(GatherUtils.contains(new Object[] {}, new Object())); 207 | 208 | Assert.assertTrue(GatherUtils.contains(new Object[] { 'a', 'b', 'c' }, 'a')); 209 | Assert.assertTrue(GatherUtils.contains(new Object[] { 'a', 'b', 'c' }, 'b')); 210 | Assert.assertTrue(GatherUtils.contains(new Object[] { 'a', 'b', 'c' }, 'c')); 211 | Assert.assertFalse(GatherUtils.contains(new Object[] { 'a', 'b', 'c' }, 'x')); 212 | Assert.assertFalse(GatherUtils.contains(new Object[] { 'a', 'b', 'c' }, 'y')); 213 | Assert.assertFalse(GatherUtils.contains(new Object[] { 'a', 'b', 'c' }, 'z')); 214 | Assert.assertTrue(GatherUtils.contains(new Object[] { 'a', 'b', 'c' }, new Character('a'))); 215 | Assert.assertFalse(GatherUtils.contains(new Object[] { 'a', 'b', 'c' }, new Character('x'))); 216 | } 217 | 218 | @Test 219 | public void testWildcardMatch() { 220 | Assert.assertTrue(GatherUtils.wildcardMatch("abc.wav", "*")); 221 | Assert.assertTrue(GatherUtils.wildcardMatch("abc.wav", "*.w?v")); 222 | Assert.assertTrue(GatherUtils.wildcardMatch("abc.wav", "*b?.wav")); 223 | Assert.assertTrue(GatherUtils.wildcardMatch("abc.wav", "*.wav")); 224 | Assert.assertTrue(GatherUtils.wildcardMatch("abc.wav", "*abc.wav")); 225 | Assert.assertTrue(GatherUtils.wildcardMatch("abc.wav", "???.wav")); 226 | Assert.assertTrue(GatherUtils.wildcardMatch("abc.wav", "???.???")); 227 | Assert.assertTrue(GatherUtils.wildcardMatch("abc.wav", "???.???")); 228 | 229 | Assert.assertFalse(GatherUtils.wildcardMatch("abc.wav", "*.html")); 230 | Assert.assertFalse(GatherUtils.wildcardMatch("abc.wav", "?.wav")); 231 | Assert.assertFalse(GatherUtils.wildcardMatch("abc.wav", "??.wav")); 232 | Assert.assertFalse(GatherUtils.wildcardMatch("abc.wav", "abc.wi?")); 233 | 234 | Assert.assertTrue(GatherUtils.wildcardMatch("http://sangupta.com/tech/page10/index.html", "*tech/page*")); 235 | } 236 | 237 | @Test 238 | public void testIsNumberType() { 239 | Assert.assertFalse(GatherUtils.isNumberType(null)); 240 | Assert.assertFalse(GatherUtils.isNumberType(new Object())); 241 | 242 | Assert.assertTrue(GatherUtils.isNumberType((byte) 123)); 243 | Assert.assertTrue(GatherUtils.isNumberType(123)); 244 | Assert.assertTrue(GatherUtils.isNumberType(123l)); 245 | Assert.assertTrue(GatherUtils.isNumberType(123f)); 246 | Assert.assertTrue(GatherUtils.isNumberType(123d)); 247 | Assert.assertTrue(GatherUtils.isNumberType(new AtomicLong(123))); 248 | Assert.assertTrue(GatherUtils.isNumberType(new AtomicInteger(123))); 249 | } 250 | 251 | @Test 252 | public void testAsNumber() { 253 | Assert.assertNull(GatherUtils.asNumber(null)); 254 | Assert.assertNull(GatherUtils.asNumber(new Object())); 255 | 256 | Assert.assertNotNull(GatherUtils.asNumber((byte) 123)); 257 | Assert.assertNotNull(GatherUtils.asNumber(123)); 258 | Assert.assertNotNull(GatherUtils.asNumber(123l)); 259 | Assert.assertNotNull(GatherUtils.asNumber(123f)); 260 | Assert.assertNotNull(GatherUtils.asNumber(123d)); 261 | Assert.assertNotNull(GatherUtils.asNumber(new AtomicLong(123))); 262 | Assert.assertNotNull(GatherUtils.asNumber(new AtomicInteger(123))); 263 | } 264 | 265 | @Test 266 | public void testRegexMatch() { 267 | Assert.assertFalse(GatherUtils.regexMatch(null, (String) null)); 268 | Assert.assertFalse(GatherUtils.regexMatch("hello world", (String) null)); 269 | 270 | Assert.assertFalse(GatherUtils.regexMatch(null, (Pattern) null)); 271 | Assert.assertFalse(GatherUtils.regexMatch("hello world", (Pattern) null)); 272 | Assert.assertFalse(GatherUtils.regexMatch(null, "\\d")); 273 | Assert.assertFalse(GatherUtils.regexMatch(null, Pattern.compile("\\d"))); 274 | 275 | Assert.assertTrue(GatherUtils.regexMatch("hello world", "^[^\\d].*")); 276 | Assert.assertFalse(GatherUtils.regexMatch("1hello world", "^[^\\d].*")); 277 | } 278 | 279 | @Test 280 | public void testContainsAllOrAnyBooleanArray() { 281 | // basic checks 282 | Assert.assertFalse(GatherUtils.containsAllOrAny((boolean[]) null, new boolean[] { false }, true)); 283 | Assert.assertFalse(GatherUtils.containsAllOrAny((boolean[]) null, new boolean[] { false }, false)); 284 | 285 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { }, new boolean[] { false }, true)); 286 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { }, new boolean[] { false }, false)); 287 | 288 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { true }, null, true)); 289 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { true }, null, false)); 290 | 291 | // all clause 292 | Assert.assertTrue(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new boolean[] { false, false }, true)); 293 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new boolean[] { false, true }, true)); 294 | 295 | Assert.assertTrue(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new Boolean[] { false, false }, true)); 296 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new Boolean[] { false, true }, true)); 297 | 298 | Assert.assertTrue(GatherUtils.containsAllOrAny(new boolean[] { false, false }, Arrays.asList(new Boolean[] { false, false }), true)); 299 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { false, false }, Arrays.asList(new Boolean[] { false, true }), true)); 300 | 301 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { false, false }, Arrays.asList(new Object[] { new Object() }), true)); 302 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { false, false }, Arrays.asList(new Object[] { new Object() }), true)); 303 | 304 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new Object(), true)); 305 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new Object(), true)); 306 | 307 | // any clause 308 | Assert.assertTrue(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new boolean[] { false, false }, false)); 309 | Assert.assertTrue(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new boolean[] { false, true }, false)); 310 | 311 | Assert.assertTrue(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new Boolean[] { false, false }, false)); 312 | Assert.assertTrue(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new Boolean[] { false, true }, false)); 313 | 314 | Assert.assertTrue(GatherUtils.containsAllOrAny(new boolean[] { false, false }, Arrays.asList(new Boolean[] { false, false }), false)); 315 | Assert.assertTrue(GatherUtils.containsAllOrAny(new boolean[] { false, false }, Arrays.asList(new Boolean[] { false, true }), false)); 316 | 317 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { false, false }, Arrays.asList(new Object[] { new Object() }), false)); 318 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { false, false }, Arrays.asList(new Object[] { new Object() }), false)); 319 | 320 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new Object(), false)); 321 | Assert.assertFalse(GatherUtils.containsAllOrAny(new boolean[] { false, false }, new Object(), false)); 322 | } 323 | 324 | @Test 325 | public void testContainsAllOrAnyCharacterArray() { 326 | // basic checks 327 | Assert.assertFalse(GatherUtils.containsAllOrAny((char[]) null, new char[] { 'a' }, true)); 328 | Assert.assertFalse(GatherUtils.containsAllOrAny((char[]) null, new char[] { 'a' }, false)); 329 | 330 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { }, new char[] { 'a' }, true)); 331 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { }, new char[] { 'a' }, false)); 332 | 333 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, null, true)); 334 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, null, false)); 335 | 336 | // all clause 337 | Assert.assertTrue(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new char[] { 'a', 'b', 'c' }, true)); 338 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new char[] { 'b', 'd' }, true)); 339 | 340 | Assert.assertTrue(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new Character[] { 'a', 'b', 'c' }, true)); 341 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new Character[] { 'b', 'd' }, true)); 342 | 343 | Assert.assertTrue(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, Arrays.asList(new Character[] { 'a', 'b', 'c' }), true)); 344 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, Arrays.asList(new Character[] { 'b', 'd' }), true)); 345 | 346 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 347 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 348 | 349 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new Object(), true)); 350 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new Object(), true)); 351 | 352 | // any clause 353 | Assert.assertTrue(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new char[] { 'a', 'b', 'c' }, false)); 354 | Assert.assertTrue(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new char[] { 'b', 'd' }, false)); 355 | 356 | Assert.assertTrue(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new Character[] { 'a', 'b', 'c' }, false)); 357 | Assert.assertTrue(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new Character[] { 'b', 'd' }, false)); 358 | 359 | Assert.assertTrue(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, Arrays.asList(new Character[] { 'a', 'b', 'c' }), false)); 360 | Assert.assertTrue(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, Arrays.asList(new Character[] { 'b', 'd' }), false)); 361 | 362 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 363 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 364 | 365 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new Object(), false)); 366 | Assert.assertFalse(GatherUtils.containsAllOrAny(new char[] { 'a', 'b', 'c' }, new Object(), false)); 367 | } 368 | 369 | @Test 370 | public void testContainsAllOrAnyByteArray() { 371 | // basic checks 372 | Assert.assertFalse(GatherUtils.containsAllOrAny((byte[]) null, new byte[] { 12 }, true)); 373 | Assert.assertFalse(GatherUtils.containsAllOrAny((byte[]) null, new byte[] { 12 }, false)); 374 | 375 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { }, new byte[] { 12 }, true)); 376 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { }, new byte[] { 12 }, false)); 377 | 378 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, null, true)); 379 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, null, false)); 380 | 381 | // all clause 382 | Assert.assertTrue(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new byte[] { 'a', 'b', 'c' }, true)); 383 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new byte[] { 'b', 'd' }, true)); 384 | 385 | Assert.assertTrue(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new Byte[] { 'a', 'b', 'c' }, true)); 386 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new Byte[] { 'b', 'd' }, true)); 387 | 388 | Assert.assertTrue(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, Arrays.asList(new Byte[] { 'a', 'b', 'c' }), true)); 389 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, Arrays.asList(new Byte[] { 'b', 'd' }), true)); 390 | 391 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 392 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 393 | 394 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new Object(), true)); 395 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new Object(), true)); 396 | 397 | // any clause 398 | Assert.assertTrue(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new byte[] { 'a', 'b', 'c' }, false)); 399 | Assert.assertTrue(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new byte[] { 'b', 'd' }, false)); 400 | 401 | Assert.assertTrue(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new Byte[] { 'a', 'b', 'c' }, false)); 402 | Assert.assertTrue(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new Byte[] { 'b', 'd' }, false)); 403 | 404 | Assert.assertTrue(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, Arrays.asList(new Byte[] { 'a', 'b', 'c' }), false)); 405 | Assert.assertTrue(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, Arrays.asList(new Byte[] { 'b', 'd' }), false)); 406 | 407 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 408 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 409 | 410 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new Object(), false)); 411 | Assert.assertFalse(GatherUtils.containsAllOrAny(new byte[] { 'a', 'b', 'c' }, new Object(), false)); 412 | } 413 | 414 | @Test 415 | public void testContainsAllOrAnyShortArray() { 416 | // basic checks 417 | Assert.assertFalse(GatherUtils.containsAllOrAny((short[]) null, new short[] { 12 }, true)); 418 | Assert.assertFalse(GatherUtils.containsAllOrAny((short[]) null, new short[] { 12 }, false)); 419 | 420 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { }, new short[] { 12 }, true)); 421 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { }, new short[] { 12 }, false)); 422 | 423 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, null, true)); 424 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, null, false)); 425 | 426 | // all clause 427 | Assert.assertTrue(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new short[] { 'a', 'b', 'c' }, true)); 428 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new short[] { 'b', 'd' }, true)); 429 | 430 | Assert.assertTrue(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new Short[] { 'a', 'b', 'c' }, true)); 431 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new Short[] { 'b', 'd' }, true)); 432 | 433 | Assert.assertTrue(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'a', 'b', 'c' }), true)); 434 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'b', 'd' }), true)); 435 | 436 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 437 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 438 | 439 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new Object(), true)); 440 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new Object(), true)); 441 | 442 | // any clause 443 | Assert.assertTrue(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new short[] { 'a', 'b', 'c' }, false)); 444 | Assert.assertTrue(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new short[] { 'b', 'd' }, false)); 445 | 446 | Assert.assertTrue(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new Short[] { 'a', 'b', 'c' }, false)); 447 | Assert.assertTrue(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new Short[] { 'b', 'd' }, false)); 448 | 449 | Assert.assertTrue(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'a', 'b', 'c' }), false)); 450 | Assert.assertTrue(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'b', 'd' }), false)); 451 | 452 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 453 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 454 | 455 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new Object(), false)); 456 | Assert.assertFalse(GatherUtils.containsAllOrAny(new short[] { 'a', 'b', 'c' }, new Object(), false)); 457 | } 458 | 459 | @Test 460 | public void testContainsAllOrAnyIntArray() { 461 | // basic checks 462 | Assert.assertFalse(GatherUtils.containsAllOrAny((int[]) null, new int[] { 12 }, true)); 463 | Assert.assertFalse(GatherUtils.containsAllOrAny((int[]) null, new int[] { 12 }, false)); 464 | 465 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { }, new int[] { 12 }, true)); 466 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { }, new int[] { 12 }, false)); 467 | 468 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, null, true)); 469 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, null, false)); 470 | 471 | // all clause 472 | Assert.assertTrue(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new int[] { 'a', 'b', 'c' }, true)); 473 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new int[] { 'b', 'd' }, true)); 474 | 475 | Assert.assertTrue(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new Short[] { 'a', 'b', 'c' }, true)); 476 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new Short[] { 'b', 'd' }, true)); 477 | 478 | Assert.assertTrue(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'a', 'b', 'c' }), true)); 479 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'b', 'd' }), true)); 480 | 481 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 482 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 483 | 484 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new Object(), true)); 485 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new Object(), true)); 486 | 487 | // any clause 488 | Assert.assertTrue(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new int[] { 'a', 'b', 'c' }, false)); 489 | Assert.assertTrue(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new int[] { 'b', 'd' }, false)); 490 | 491 | Assert.assertTrue(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new Short[] { 'a', 'b', 'c' }, false)); 492 | Assert.assertTrue(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new Short[] { 'b', 'd' }, false)); 493 | 494 | Assert.assertTrue(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'a', 'b', 'c' }), false)); 495 | Assert.assertTrue(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'b', 'd' }), false)); 496 | 497 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 498 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 499 | 500 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new Object(), false)); 501 | Assert.assertFalse(GatherUtils.containsAllOrAny(new int[] { 'a', 'b', 'c' }, new Object(), false)); 502 | } 503 | 504 | @Test 505 | public void testContainsAllOrAnyLongArray() { 506 | // basic checks 507 | Assert.assertFalse(GatherUtils.containsAllOrAny((long[]) null, new long[] { 12 }, true)); 508 | Assert.assertFalse(GatherUtils.containsAllOrAny((long[]) null, new long[] { 12 }, false)); 509 | 510 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { }, new long[] { 12 }, true)); 511 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { }, new long[] { 12 }, false)); 512 | 513 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, null, true)); 514 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, null, false)); 515 | 516 | // all clause 517 | Assert.assertTrue(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new long[] { 'a', 'b', 'c' }, true)); 518 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new long[] { 'b', 'd' }, true)); 519 | 520 | Assert.assertTrue(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new Short[] { 'a', 'b', 'c' }, true)); 521 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new Short[] { 'b', 'd' }, true)); 522 | 523 | Assert.assertTrue(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'a', 'b', 'c' }), true)); 524 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'b', 'd' }), true)); 525 | 526 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 527 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 528 | 529 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new Object(), true)); 530 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new Object(), true)); 531 | 532 | // any clause 533 | Assert.assertTrue(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new long[] { 'a', 'b', 'c' }, false)); 534 | Assert.assertTrue(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new long[] { 'b', 'd' }, false)); 535 | 536 | Assert.assertTrue(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new Short[] { 'a', 'b', 'c' }, false)); 537 | Assert.assertTrue(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new Short[] { 'b', 'd' }, false)); 538 | 539 | Assert.assertTrue(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'a', 'b', 'c' }), false)); 540 | Assert.assertTrue(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'b', 'd' }), false)); 541 | 542 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 543 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 544 | 545 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new Object(), false)); 546 | Assert.assertFalse(GatherUtils.containsAllOrAny(new long[] { 'a', 'b', 'c' }, new Object(), false)); 547 | } 548 | 549 | @Test 550 | public void testContainsAllOrAnyFloatArray() { 551 | // basic checks 552 | Assert.assertFalse(GatherUtils.containsAllOrAny((float[]) null, new float[] { 12 }, true)); 553 | Assert.assertFalse(GatherUtils.containsAllOrAny((float[]) null, new float[] { 12 }, false)); 554 | 555 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { }, new float[] { 12 }, true)); 556 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { }, new float[] { 12 }, false)); 557 | 558 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, null, true)); 559 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, null, false)); 560 | 561 | // all clause 562 | Assert.assertTrue(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new float[] { 'a', 'b', 'c' }, true)); 563 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new float[] { 'b', 'd' }, true)); 564 | 565 | Assert.assertTrue(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new Short[] { 'a', 'b', 'c' }, true)); 566 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new Short[] { 'b', 'd' }, true)); 567 | 568 | Assert.assertTrue(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'a', 'b', 'c' }), true)); 569 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'b', 'd' }), true)); 570 | 571 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 572 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 573 | 574 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new Object(), true)); 575 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new Object(), true)); 576 | 577 | // any clause 578 | Assert.assertTrue(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new float[] { 'a', 'b', 'c' }, false)); 579 | Assert.assertTrue(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new float[] { 'b', 'd' }, false)); 580 | 581 | Assert.assertTrue(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new Short[] { 'a', 'b', 'c' }, false)); 582 | Assert.assertTrue(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new Short[] { 'b', 'd' }, false)); 583 | 584 | Assert.assertTrue(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'a', 'b', 'c' }), false)); 585 | Assert.assertTrue(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'b', 'd' }), false)); 586 | 587 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 588 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 589 | 590 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new Object(), false)); 591 | Assert.assertFalse(GatherUtils.containsAllOrAny(new float[] { 'a', 'b', 'c' }, new Object(), false)); 592 | } 593 | 594 | @Test 595 | public void testContainsAllOrAnyDoubleArray() { 596 | // basic checks 597 | Assert.assertFalse(GatherUtils.containsAllOrAny((double[]) null, new double[] { 12 }, true)); 598 | Assert.assertFalse(GatherUtils.containsAllOrAny((double[]) null, new double[] { 12 }, false)); 599 | 600 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { }, new double[] { 12 }, true)); 601 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { }, new double[] { 12 }, false)); 602 | 603 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, null, true)); 604 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, null, false)); 605 | 606 | // all clause 607 | Assert.assertTrue(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new double[] { 'a', 'b', 'c' }, true)); 608 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new double[] { 'b', 'd' }, true)); 609 | 610 | Assert.assertTrue(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new Short[] { 'a', 'b', 'c' }, true)); 611 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new Short[] { 'b', 'd' }, true)); 612 | 613 | Assert.assertTrue(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'a', 'b', 'c' }), true)); 614 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'b', 'd' }), true)); 615 | 616 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 617 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 618 | 619 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new Object(), true)); 620 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new Object(), true)); 621 | 622 | // any clause 623 | Assert.assertTrue(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new double[] { 'a', 'b', 'c' }, false)); 624 | Assert.assertTrue(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new double[] { 'b', 'd' }, false)); 625 | 626 | Assert.assertTrue(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new Short[] { 'a', 'b', 'c' }, false)); 627 | Assert.assertTrue(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new Short[] { 'b', 'd' }, false)); 628 | 629 | Assert.assertTrue(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'a', 'b', 'c' }), false)); 630 | Assert.assertTrue(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, Arrays.asList(new Short[] { 'b', 'd' }), false)); 631 | 632 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 633 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 634 | 635 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new Object(), false)); 636 | Assert.assertFalse(GatherUtils.containsAllOrAny(new double[] { 'a', 'b', 'c' }, new Object(), false)); 637 | } 638 | 639 | @Test 640 | public void testContainsAllOrAnyObjectArray() { 641 | // basic checks 642 | Assert.assertFalse(GatherUtils.containsAllOrAny((Object[]) null, new double[] { 12 }, true)); 643 | Assert.assertFalse(GatherUtils.containsAllOrAny((Object[]) null, new double[] { 12 }, false)); 644 | 645 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { }, new double[] { 12 }, true)); 646 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { }, new double[] { 12 }, false)); 647 | 648 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, null, true)); 649 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, null, false)); 650 | 651 | // all clause 652 | Assert.assertTrue(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object[] { 'a', 'b', 'c' }, true)); 653 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object[] { 'b', 'd' }, true)); 654 | 655 | Assert.assertTrue(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object[] { 'a', 'b', 'c' }, true)); 656 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object[] { 'b', 'd' }, true)); 657 | 658 | Assert.assertTrue(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { 'a', 'b', 'c' }), true)); 659 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { 'b', 'd' }), true)); 660 | 661 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 662 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), true)); 663 | 664 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object(), true)); 665 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object(), true)); 666 | 667 | // any clause 668 | Assert.assertTrue(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object[] { 'a', 'b', 'c' }, false)); 669 | Assert.assertTrue(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object[] { 'b', 'd' }, false)); 670 | 671 | Assert.assertTrue(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object[] { 'a', 'b', 'c' }, false)); 672 | Assert.assertTrue(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object[] { 'b', 'd' }, false)); 673 | 674 | Assert.assertTrue(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { 'a', 'b', 'c' }), false)); 675 | Assert.assertTrue(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { 'b', 'd' }), false)); 676 | 677 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 678 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, Arrays.asList(new Object[] { new Object() }), false)); 679 | 680 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object(), false)); 681 | Assert.assertFalse(GatherUtils.containsAllOrAny(new Object[] { 'a', 'b', 'c' }, new Object(), false)); 682 | } 683 | 684 | @Test 685 | public void testContainsAllOrAnyObjectCollection() { 686 | // basic checks 687 | Assert.assertFalse(GatherUtils.containsAllOrAny((List) null, new double[] { 12 }, true)); 688 | Assert.assertFalse(GatherUtils.containsAllOrAny((List) null, new double[] { 12 }, false)); 689 | 690 | List list = new ArrayList<>(); 691 | 692 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, new double[] { 12 }, true)); 693 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, new double[] { 12 }, false)); 694 | 695 | list.add('a'); 696 | list.add('b'); 697 | list.add('c'); 698 | 699 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, null, true)); 700 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, null, false)); 701 | 702 | // all clause 703 | Assert.assertTrue(GatherUtils.containsAllOrAny(list, new Object[] { 'a', 'b', 'c' }, true)); 704 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, new Object[] { 'b', 'd' }, true)); 705 | 706 | Assert.assertTrue(GatherUtils.containsAllOrAny(list, new Object[] { 'a', 'b', 'c' }, true)); 707 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, new Object[] { 'b', 'd' }, true)); 708 | 709 | Assert.assertTrue(GatherUtils.containsAllOrAny(list, Arrays.asList(new Object[] { 'a', 'b', 'c' }), true)); 710 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, Arrays.asList(new Object[] { 'b', 'd' }), true)); 711 | 712 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, Arrays.asList(new Object[] { new Object() }), true)); 713 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, Arrays.asList(new Object[] { new Object() }), true)); 714 | 715 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, new Object(), true)); 716 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, new Object(), true)); 717 | 718 | // any clause 719 | Assert.assertTrue(GatherUtils.containsAllOrAny(list, new Object[] { 'a', 'b', 'c' }, false)); 720 | Assert.assertTrue(GatherUtils.containsAllOrAny(list, new Object[] { 'b', 'd' }, false)); 721 | 722 | Assert.assertTrue(GatherUtils.containsAllOrAny(list, new Object[] { 'a', 'b', 'c' }, false)); 723 | Assert.assertTrue(GatherUtils.containsAllOrAny(list, new Object[] { 'b', 'd' }, false)); 724 | 725 | Assert.assertTrue(GatherUtils.containsAllOrAny(list, Arrays.asList(new Object[] { 'a', 'b', 'c' }), false)); 726 | Assert.assertTrue(GatherUtils.containsAllOrAny(list, Arrays.asList(new Object[] { 'b', 'd' }), false)); 727 | 728 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, Arrays.asList(new Object[] { new Object() }), false)); 729 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, Arrays.asList(new Object[] { new Object() }), false)); 730 | 731 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, new Object(), false)); 732 | Assert.assertFalse(GatherUtils.containsAllOrAny(list, new Object(), false)); 733 | } 734 | 735 | @Test 736 | public void testCompareNumbers() { 737 | Assert.assertTrue(GatherUtils.compareNumbers((byte) 32, 64d) < 0); 738 | Assert.assertTrue(GatherUtils.compareNumbers((short) 32, 64d) < 0); 739 | Assert.assertTrue(GatherUtils.compareNumbers((int) 32, 64d) < 0); 740 | Assert.assertTrue(GatherUtils.compareNumbers((long) 32, 64d) < 0); 741 | Assert.assertTrue(GatherUtils.compareNumbers((float) 32, 64d) < 0); 742 | Assert.assertTrue(GatherUtils.compareNumbers((double) 32, new AtomicLong(64)) < 0); 743 | 744 | Assert.assertTrue(GatherUtils.compareNumbers(new AtomicInteger(32), new AtomicLong(64)) < 0); 745 | Assert.assertTrue(GatherUtils.compareNumbers(new AtomicLong(32), (short) 64) < 0); 746 | 747 | Assert.assertTrue(GatherUtils.compareNumbers(new BigDecimal(32), new BigDecimal(64)) < 0); 748 | Assert.assertTrue(GatherUtils.compareNumbers(new BigDecimal(32), (byte) 64) < 0); 749 | Assert.assertTrue(GatherUtils.compareNumbers(new BigDecimal(32), (short) 64) < 0); 750 | Assert.assertTrue(GatherUtils.compareNumbers(new BigDecimal(32), (int) 64) < 0); 751 | Assert.assertTrue(GatherUtils.compareNumbers(new BigDecimal(32), (long) 64) < 0); 752 | Assert.assertTrue(GatherUtils.compareNumbers(new BigDecimal(32), (float) 64) < 0); 753 | Assert.assertTrue(GatherUtils.compareNumbers(new BigDecimal(32), (double) 64) < 0); 754 | Assert.assertTrue(GatherUtils.compareNumbers(new BigDecimal(32), new AtomicInteger(64)) < 0); 755 | Assert.assertTrue(GatherUtils.compareNumbers(new BigDecimal(32), new AtomicLong(64)) < 0); 756 | 757 | } 758 | } 759 | --------------------------------------------------------------------------------