/protostuffdb-core/src/main/java/com/dyuproject/protostuffdb/Validation.java

https://gitlab.com/dyu/protostuffdb · Java · 1485 lines · 1091 code · 250 blank · 144 comment · 321 complexity · 0ebc920a889433f10ccc5fa96cb501b1 MD5 · raw file

  1. //========================================================================
  2. //Copyright 2012 David Yu
  3. //------------------------------------------------------------------------
  4. //Licensed under the Apache License, Version 2.0 (the "License");
  5. //you may not use this file except in compliance with the License.
  6. //You may obtain a copy of the License at
  7. //http://www.apache.org/licenses/LICENSE-2.0
  8. //Unless required by applicable law or agreed to in writing, software
  9. //distributed under the License is distributed on an "AS IS" BASIS,
  10. //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. //See the License for the specific language governing permissions and
  12. //limitations under the License.
  13. //========================================================================
  14. package com.dyuproject.protostuffdb;
  15. import static com.dyuproject.protostuffdb.DateTimeUtil.MILLIS_PER_DAY;
  16. import static com.dyuproject.protostuffdb.DateTimeUtil.startOfTodayMS;
  17. import java.math.BigDecimal;
  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.Collection;
  21. import java.util.Date;
  22. import java.util.HashMap;
  23. import java.util.List;
  24. import java.util.TreeMap;
  25. import java.util.regex.Pattern;
  26. import com.dyuproject.protostuff.LongHashSet;
  27. import com.dyuproject.protostuff.ds.CAS;
  28. /**
  29. * Validation for scalar fields.
  30. *
  31. * @author David Yu
  32. * @created Oct 22, 2012
  33. */
  34. public final class Validation
  35. {
  36. static final Pattern PATTERN_EMAIL =
  37. Pattern.compile("^[+a-zA-Z0-9_.-]+@([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9]{2,6}$");
  38. // start misc
  39. public static boolean isAsciiOnly(String value)
  40. {
  41. for (int i = 0, len = value.length(); i < len; i++)
  42. {
  43. if (value.charAt(i) > 127)
  44. return false;
  45. }
  46. return true;
  47. }
  48. public static boolean isAsciiPrintable(String value)
  49. {
  50. char c;
  51. for (int i = 0, len = value.length(); i < len; i++)
  52. {
  53. c = value.charAt(i);
  54. if (c < 32 || c > 127)
  55. return false;
  56. }
  57. return true;
  58. }
  59. public static boolean isAsciiSafeHtml(String value)
  60. {
  61. char c;
  62. for (int i = 0, len = value.length(); i < len; i++)
  63. {
  64. c = value.charAt(i);
  65. if (c < 32 || c > 127 || c == '&' || c == '<' || c == '>' || c == '\\')
  66. return false;
  67. }
  68. return true;
  69. }
  70. /**
  71. * Returns true if null or empty.
  72. */
  73. public static boolean isEmpty(CAS cas)
  74. {
  75. return cas == null || cas.isEmpty();
  76. }
  77. /**
  78. * Returns true if null or empty.
  79. */
  80. public static boolean isEmpty(List<?> list)
  81. {
  82. return list == null || list.isEmpty();
  83. }
  84. /**
  85. * Returns true if null or empty.
  86. */
  87. public static boolean isEmpty(String value)
  88. {
  89. return value == null || 0 == value.length();
  90. }
  91. /**
  92. * Returns true if null or empty.
  93. */
  94. public static boolean isEmpty(byte[] value)
  95. {
  96. return value == null || 0 == value.length;
  97. }
  98. /**
  99. * Returns true if its an id.
  100. */
  101. public static boolean isValidId(int id)
  102. {
  103. return id > 0;
  104. }
  105. /**
  106. * Returns true if its a key.
  107. */
  108. public static boolean isValidKey(byte[] key)
  109. {
  110. return key != null && KeyUtil.isKey(key);
  111. }
  112. // end misc
  113. /*static
  114. {
  115. String atom = "[a-z0-9!#$%&'*+/=?^_`{|}~-]";
  116. String domain = "(" + atom + "+(\\." + atom + "+)*";
  117. String ip_domain = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]";
  118. PATTERN_EMAIL = Pattern.compile(
  119. "^" + atom + "+(\\." + atom + "+)*@"
  120. + domain
  121. + "|"
  122. + ip_domain
  123. + ")$",
  124. Pattern.CASE_INSENSITIVE);
  125. }*/
  126. // TODO optimize
  127. public static boolean isValidUnique(
  128. final List<byte[]> list)
  129. {
  130. if (list == null || list.isEmpty())
  131. return true;
  132. final int len = list.size();
  133. switch (len)
  134. {
  135. case 1:
  136. return true;
  137. case 2:
  138. return !Arrays.equals(list.get(0), list.get(1));
  139. }
  140. final TreeMap<byte[],Boolean> map = new TreeMap<byte[],Boolean>(Comparators.DEFAULT);
  141. for (int i = 0; i < len; i++)
  142. {
  143. if (null != map.put(list.get(i), Boolean.TRUE))
  144. return false;
  145. }
  146. /*final LongHashSet set = new LongHashSet(len + extraCapacity);
  147. for (int i = 0; i < len; i++)
  148. {
  149. byte[] key = list.get(i);
  150. long val = ValueUtil.toInt64LE(key, 1);
  151. if (!set.add(val))
  152. return addMessage(message);
  153. }*/
  154. return true;
  155. }
  156. public static boolean isValidUnique(
  157. final List<byte[]> list, final int kind)
  158. {
  159. if (list == null || list.isEmpty())
  160. return true;
  161. final int len = list.size();
  162. switch (len)
  163. {
  164. case 1:
  165. return KeyUtil.isKey(list.get(0), kind);
  166. case 2:
  167. return KeyUtil.isKey(list.get(0), kind) &&
  168. KeyUtil.isKey(list.get(1), kind) &&
  169. !Arrays.equals(list.get(0), list.get(1));
  170. }
  171. // TODO should really be twice the len?
  172. final int extraCapacity = len;
  173. final LongHashSet set = new LongHashSet(len + extraCapacity);
  174. for (int i = 0; i < len; i++)
  175. {
  176. byte[] key = list.get(i);
  177. if (!KeyUtil.isKey(key, kind) || !set.add(ValueUtil.toInt64LE(key, 1)))
  178. return false;
  179. }
  180. return true;
  181. }
  182. public static boolean isValidUnique(
  183. final List<String> list, String dummy)
  184. {
  185. if (list == null || list.isEmpty())
  186. return true;
  187. final int len = list.size();
  188. switch (len)
  189. {
  190. case 1:
  191. return true;
  192. case 2:
  193. return !list.get(0).equals(list.get(1));
  194. }
  195. // TODO should really be twice the len?
  196. final int extraCapacity = len;
  197. final HashMap<String,Boolean> map = new HashMap<String, Boolean>(len + extraCapacity);
  198. for (int i = 0; i < len; i++)
  199. {
  200. if (null != map.put(list.get(i), Boolean.TRUE))
  201. return false;
  202. }
  203. return true;
  204. }
  205. public static boolean isValidUnique(
  206. final List<Integer> list, Integer dummy)
  207. {
  208. if (list == null || list.isEmpty())
  209. return true;
  210. final int len = list.size();
  211. switch (len)
  212. {
  213. case 1:
  214. return true;
  215. case 2:
  216. return list.get(0).intValue() != list.get(1).intValue();
  217. }
  218. // TODO should really be twice the len?
  219. final int extraCapacity = len;
  220. final LongHashSet set = new LongHashSet(len + extraCapacity);
  221. for (int i = 0; i < len; i++)
  222. {
  223. if (!set.add(list.get(i).longValue()))
  224. return false;
  225. }
  226. return true;
  227. }
  228. public static boolean isValidUnique(
  229. final List<Integer> list, final int min, Integer dummy)
  230. {
  231. if (list == null || list.isEmpty())
  232. return true;
  233. final int len = list.size();
  234. switch (len)
  235. {
  236. case 1:
  237. return list.get(0).intValue() >= min;
  238. case 2:
  239. {
  240. final int val0 = list.get(0).intValue(),
  241. val1 = list.get(1).intValue();
  242. return val0 >= min && val1 >= min && val0 != val1;
  243. }
  244. }
  245. // TODO should really be twice the len?
  246. final int extraCapacity = len;
  247. final LongHashSet set = new LongHashSet(len + extraCapacity);
  248. for (int i = 0; i < len; i++)
  249. {
  250. int val = list.get(i).intValue();
  251. if (val < min || !set.add((long)val))
  252. return false;
  253. }
  254. return true;
  255. }
  256. public static boolean isValidUnique(
  257. final List<Long> list, Long dummy)
  258. {
  259. if (list == null || list.isEmpty())
  260. return true;
  261. final int len = list.size();
  262. switch (len)
  263. {
  264. case 1:
  265. return true;
  266. case 2:
  267. return list.get(0).longValue() != list.get(1).longValue();
  268. }
  269. // TODO should really be twice the len?
  270. final int extraCapacity = len;
  271. final LongHashSet set = new LongHashSet(len + extraCapacity);
  272. for (int i = 0; i < len; i++)
  273. {
  274. if (!set.add(list.get(i)))
  275. return false;
  276. }
  277. return true;
  278. }
  279. public static boolean isValidUnique(
  280. final List<Long> list, final long min, Long dummy)
  281. {
  282. if (list == null || list.isEmpty())
  283. return true;
  284. final int len = list.size();
  285. switch (len)
  286. {
  287. case 1:
  288. return list.get(0).longValue() >= min;
  289. case 2:
  290. {
  291. final long val0 = list.get(0),
  292. val1 = list.get(1);
  293. return val0 >= min && val1 >= min && val0 != val1;
  294. }
  295. }
  296. // TODO should really be twice the len?
  297. final int extraCapacity = len;
  298. final LongHashSet set = new LongHashSet(len + extraCapacity);
  299. for (int i = 0; i < len; i++)
  300. {
  301. long val = list.get(i);
  302. if (val < min || !set.add(val))
  303. return false;
  304. }
  305. return true;
  306. }
  307. public static <T extends HasId> boolean isValidUnique(
  308. final List<T> list, final int min, HasId dummy)
  309. {
  310. if (list == null || list.isEmpty())
  311. return true;
  312. final int len = list.size();
  313. switch (len)
  314. {
  315. case 1:
  316. return list.get(0).getId() >= min;
  317. case 2:
  318. {
  319. final int val0 = list.get(0).getId(),
  320. val1 = list.get(1).getId();
  321. return val0 >= min && val1 >= min && val0 != val1;
  322. }
  323. }
  324. // TODO should really be twice the len?
  325. final int extraCapacity = len;
  326. final LongHashSet set = new LongHashSet(len + extraCapacity);
  327. for (int i = 0; i < len; i++)
  328. {
  329. int val = list.get(i).getId();
  330. if (val < min || !set.add((long)val))
  331. return false;
  332. }
  333. return true;
  334. }
  335. /**
  336. * If kind is zero, it is assumed that the key was validated with a kind before this
  337. * call.
  338. */
  339. public static <T extends HasKey> boolean isValidUnique(
  340. final List<T> list, final int kind, HasKey dummy)
  341. {
  342. if (list == null || list.isEmpty())
  343. return true;
  344. final int len = list.size();
  345. switch (len)
  346. {
  347. case 1:
  348. return kind == 0 || KeyUtil.isKey(list.get(0).getKey(), kind);
  349. case 2:
  350. {
  351. if (kind == 0)
  352. return !Arrays.equals(list.get(0).getKey(), list.get(1).getKey());
  353. final byte[] key0 = list.get(0).getKey(),
  354. key1 = list.get(1).getKey();
  355. return KeyUtil.isKey(key0, kind) && KeyUtil.isKey(key1, kind) &&
  356. !Arrays.equals(key0, key1);
  357. }
  358. }
  359. // TODO should really be twice the len?
  360. final int extraCapacity = len;
  361. final LongHashSet set = new LongHashSet(len + extraCapacity);
  362. if (kind == 0)
  363. {
  364. for (int i = 0; i < len; i++)
  365. {
  366. if (!set.add(ValueUtil.toInt64LE(list.get(i).getKey(), 1)))
  367. return false;
  368. }
  369. }
  370. else
  371. {
  372. for (int i = 0; i < len; i++)
  373. {
  374. byte[] key = list.get(i).getKey();
  375. if (!KeyUtil.isKey(key, kind) || !set.add(ValueUtil.toInt64LE(key, 1)))
  376. return false;
  377. }
  378. }
  379. return true;
  380. }
  381. /**
  382. * If kind is zero, it is assumed that the key was validated with a kind before this
  383. * call.
  384. */
  385. public static <T extends HasParentKey> boolean isValidUnique(
  386. final List<T> list, final int kind, HasParentKey dummy)
  387. {
  388. if (list == null || list.isEmpty())
  389. return true;
  390. final int len = list.size();
  391. switch (len)
  392. {
  393. case 1:
  394. return kind == 0 || KeyUtil.isKey(list.get(0).getParentKey(), kind);
  395. case 2:
  396. {
  397. if (kind == 0)
  398. return !Arrays.equals(list.get(0).getParentKey(), list.get(1).getParentKey());
  399. final byte[] key0 = list.get(0).getParentKey(),
  400. key1 = list.get(1).getParentKey();
  401. return KeyUtil.isKey(key0, kind) && KeyUtil.isKey(key1, kind) &&
  402. !Arrays.equals(key0, key1);
  403. }
  404. }
  405. // TODO should really be twice the len?
  406. final int extraCapacity = len;
  407. final LongHashSet set = new LongHashSet(len + extraCapacity);
  408. if (kind == 0)
  409. {
  410. for (int i = 0; i < len; i++)
  411. {
  412. if (!set.add(ValueUtil.toInt64LE(list.get(i).getParentKey(), 1)))
  413. return false;
  414. }
  415. }
  416. else
  417. {
  418. for (int i = 0; i < len; i++)
  419. {
  420. byte[] key = list.get(i).getParentKey();
  421. if (!KeyUtil.isKey(key, kind) || !set.add(ValueUtil.toInt64LE(key, 1)))
  422. return false;
  423. }
  424. }
  425. return true;
  426. }
  427. /**
  428. * If kind is zero, it is assumed that the key was validated with a kind before this
  429. * call.
  430. */
  431. public static <T extends HasId, K extends HasKey> boolean isValidUnique(
  432. final List<T> idlist, final int min,
  433. final List<K> keylist, final int kind)
  434. {
  435. if (idlist == null || idlist.isEmpty() || keylist == null || keylist.isEmpty())
  436. return false;
  437. final int idlen = idlist.size(), keylen = keylist.size();
  438. LongHashSet set = null;
  439. switch (idlen)
  440. {
  441. case 1:
  442. if (idlist.get(0).getId() >= min)
  443. break;
  444. return false;
  445. case 2:
  446. {
  447. final int val0 = idlist.get(0).getId(),
  448. val1 = idlist.get(1).getId();
  449. if (val0 >= min && val1 >= min && val0 != val1)
  450. break;
  451. return false;
  452. }
  453. default:
  454. set = new LongHashSet(2 * Math.max(idlen, keylen));
  455. for (int i = 0; i < idlen; i++)
  456. {
  457. int val = idlist.get(i).getId();
  458. if (val < min || !set.add((long)val))
  459. return false;
  460. }
  461. }
  462. switch (keylen)
  463. {
  464. case 1:
  465. return kind == 0 || KeyUtil.isKey(keylist.get(0).getKey(), kind);
  466. case 2:
  467. {
  468. if (kind == 0)
  469. return !Arrays.equals(keylist.get(0).getKey(), keylist.get(1).getKey());
  470. final byte[] key0 = keylist.get(0).getKey(),
  471. key1 = keylist.get(1).getKey();
  472. return KeyUtil.isKey(key0, kind) && KeyUtil.isKey(key1, kind) &&
  473. !Arrays.equals(key0, key1);
  474. }
  475. }
  476. if (set == null)
  477. set = new LongHashSet(2 * keylen);
  478. else
  479. set.clear();
  480. if (kind == 0)
  481. {
  482. for (int i = 0; i < keylen; i++)
  483. {
  484. if (!set.add(ValueUtil.toInt64LE(keylist.get(i).getKey(), 1)))
  485. return false;
  486. }
  487. }
  488. else
  489. {
  490. for (int i = 0; i < keylen; i++)
  491. {
  492. byte[] key = keylist.get(i).getKey();
  493. if (!KeyUtil.isKey(key, kind) || !set.add(ValueUtil.toInt64LE(key, 1)))
  494. return false;
  495. }
  496. }
  497. return true;
  498. }
  499. public static <T extends HasKeys> boolean isValidUniqueKeys(
  500. final List<T> list, final int ... indices)
  501. {
  502. if (list == null || list.isEmpty())
  503. return true;
  504. final int len = list.size();
  505. // TODO should really be twice the len?
  506. final int extraCapacity = len;
  507. final HasKeys first = list.get(0);
  508. LongHashSet set = null;
  509. for (int index : indices)
  510. {
  511. List<byte[]> keys = first.keysAt(index);
  512. if (keys == null)
  513. {
  514. if (len == 1)
  515. continue;
  516. if (len == 2)
  517. {
  518. if (Arrays.equals(first.keyAt(index), list.get(1).keyAt(index)))
  519. return false;
  520. continue;
  521. }
  522. if (set == null)
  523. set = new LongHashSet(len + extraCapacity);
  524. else
  525. set.clear();
  526. if (!set.add(ValueUtil.toInt64LE(first.keyAt(index), 1)))
  527. return false;
  528. for (int i = 1; i < len; i++)
  529. {
  530. if (!set.add(ValueUtil.toInt64LE(list.get(i).keyAt(index), 1)))
  531. return false;
  532. }
  533. continue;
  534. }
  535. if (set == null)
  536. {
  537. // used as multiplier (configurable from annotations)
  538. set = new LongHashSet(len + extraCapacity);
  539. /*int totalLen = keys.size();
  540. for (int i = 1; i < len; i++)
  541. totalLen = totalLen + extraCapacity + list.get(i).keysAt(index).size();
  542. set = new LongHashSet(totalLen);*/
  543. }
  544. else
  545. {
  546. set.clear();
  547. }
  548. for (byte[] key : keys)
  549. {
  550. if (!set.add(ValueUtil.toInt64LE(key, 1)))
  551. return false;
  552. }
  553. for (int i = 1; i < len; i++)
  554. {
  555. keys = list.get(i).keysAt(index);
  556. for (byte[] key : keys)
  557. {
  558. if (!set.add(ValueUtil.toInt64LE(key, 1)))
  559. return false;
  560. }
  561. }
  562. }
  563. return true;
  564. }
  565. public static <T extends HasKeys> boolean isValidUniqueKeys(
  566. final List<T> list, final int index)
  567. {
  568. if (list == null || list.isEmpty())
  569. return true;
  570. final int len = list.size();
  571. // TODO should really be twice the len?
  572. final int extraCapacity = len;
  573. final HasKeys first = list.get(0);
  574. List<byte[]> keys = first.keysAt(index);
  575. if (keys == null)
  576. {
  577. if (len == 1)
  578. return true;
  579. if (len == 2)
  580. {
  581. if (Arrays.equals(first.keyAt(index), list.get(1).keyAt(index)))
  582. return false;
  583. return true;
  584. }
  585. final LongHashSet set = new LongHashSet(len + extraCapacity);
  586. if (!set.add(ValueUtil.toInt64LE(first.keyAt(index), 1)))
  587. return false;
  588. for (int i = 1; i < len; i++)
  589. {
  590. if (!set.add(ValueUtil.toInt64LE(list.get(i).keyAt(index), 1)))
  591. return false;
  592. }
  593. return true;
  594. }
  595. // used as multiplier (configurable from annotations)
  596. final LongHashSet set = new LongHashSet(len + extraCapacity);
  597. /*int totalLen = keys.size();
  598. for (int i = 1; i < len; i++)
  599. totalLen = totalLen + extraCapacity + list.get(i).keysAt(index).size();
  600. final LongHashSet set = new LongHashSet(totalLen);*/
  601. for (byte[] key : keys)
  602. {
  603. if (!set.add(ValueUtil.toInt64LE(key, 1)))
  604. return false;
  605. }
  606. for (int i = 1; i < len; i++)
  607. {
  608. keys = list.get(i).keysAt(index);
  609. for (byte[] key : keys)
  610. {
  611. if (!set.add(ValueUtil.toInt64LE(key, 1)))
  612. return false;
  613. }
  614. }
  615. return true;
  616. }
  617. public static <T extends HasIds> boolean isValidUniqueIds(
  618. final List<T> list, final int ... indices)
  619. {
  620. if (list == null || list.isEmpty())
  621. return true;
  622. final int len = list.size();
  623. // TODO should really be twice the len?
  624. final int extraCapacity = len;
  625. final HasIds first = list.get(0);
  626. LongHashSet set = null;
  627. for (int index : indices)
  628. {
  629. List<Integer> ids = first.idsAt(index);
  630. if (ids == null)
  631. {
  632. if (len == 1)
  633. continue;
  634. if (len == 2)
  635. {
  636. if (first.idAt(index) == list.get(1).idAt(index))
  637. return false;
  638. continue;
  639. }
  640. if (set == null)
  641. set = new LongHashSet(len + extraCapacity);
  642. else
  643. set.clear();
  644. if (!set.add((long)first.idAt(index)))
  645. return false;
  646. for (int i = 1; i < len; i++)
  647. {
  648. if (!set.add((long)list.get(i).idAt(index)))
  649. return false;
  650. }
  651. continue;
  652. }
  653. if (set == null)
  654. {
  655. // used as multiplier (configurable from annotations)
  656. set = new LongHashSet(len + extraCapacity);
  657. /*int totalLen = ids.size();
  658. for (int i = 1; i < len; i++)
  659. totalLen = totalLen + extraCapacity + list.get(i).idsAt(index).size();
  660. set = new LongHashSet(totalLen);*/
  661. }
  662. else
  663. {
  664. set.clear();
  665. }
  666. for (Integer id : ids)
  667. {
  668. if (!set.add(id.longValue()))
  669. return false;
  670. }
  671. for (int i = 1; i < len; i++)
  672. {
  673. ids = list.get(i).idsAt(index);
  674. for (Integer id : ids)
  675. {
  676. if (!set.add(id.longValue()))
  677. return false;
  678. }
  679. }
  680. }
  681. return true;
  682. }
  683. public static <T extends HasIds> boolean isValidUniqueIds(
  684. final List<T> list, final int index)
  685. {
  686. if (list == null || list.isEmpty())
  687. return true;
  688. final int len = list.size();
  689. // TODO should really be twice the len?
  690. final int extraCapacity = len;
  691. final HasIds first = list.get(0);
  692. List<Integer> ids = first.idsAt(index);
  693. if (ids == null)
  694. {
  695. if (len == 1)
  696. return true;
  697. if (len == 2)
  698. {
  699. if (first.idAt(index) == list.get(1).idAt(index))
  700. return false;
  701. return true;
  702. }
  703. final LongHashSet set = new LongHashSet(len + extraCapacity);
  704. if (!set.add((long)first.idAt(index)))
  705. return false;
  706. for (int i = 1; i < len; i++)
  707. {
  708. if (!set.add((long)list.get(i).idAt(index)))
  709. return false;
  710. }
  711. return true;
  712. }
  713. // used as multiplier (configurable from annotations)
  714. final LongHashSet set = new LongHashSet(len + extraCapacity);
  715. /*int totalLen = ids.size();
  716. for (int i = 1; i < len; i++)
  717. totalLen = totalLen + extraCapacity + list.get(i).idsAt(index).size();
  718. final LongHashSet set = new LongHashSet(totalLen);*/
  719. for (Integer id : ids)
  720. {
  721. if (!set.add(id.longValue()))
  722. return false;
  723. }
  724. for (int i = 1; i < len; i++)
  725. {
  726. ids = list.get(i).idsAt(index);
  727. for (Integer id : ids)
  728. {
  729. if (!set.add(id.longValue()))
  730. return false;
  731. }
  732. }
  733. return true;
  734. }
  735. public static boolean isValidTime(int value)
  736. {
  737. return isValidRange(value, 0, DateTimeUtil.MAX_TIME);
  738. }
  739. public static boolean isValidDate(long value)
  740. {
  741. return 0 == value % MILLIS_PER_DAY;
  742. }
  743. public static boolean isValidDecimalMax(BigDecimal value, BigDecimal maxValue)
  744. {
  745. return value.compareTo(maxValue) != 1;
  746. }
  747. public static boolean isValidDecimalMax(String value, BigDecimal maxValue)
  748. {
  749. try
  750. {
  751. return isValidDecimalMax(new BigDecimal(value), maxValue);
  752. }
  753. catch (NumberFormatException e)
  754. {
  755. return false;
  756. }
  757. }
  758. public static boolean isValidDecimalMax(float value, float maxValue)
  759. {
  760. return value <= maxValue;
  761. }
  762. public static boolean isValidDecimalMax(double value, double maxValue)
  763. {
  764. return value <= maxValue;
  765. }
  766. public static boolean isValidDecimalMin(BigDecimal value, BigDecimal minValue)
  767. {
  768. return value.compareTo(minValue) != -1;
  769. }
  770. public static boolean isValidDecimalMin(String value, BigDecimal minValue)
  771. {
  772. try
  773. {
  774. return isValidDecimalMin(new BigDecimal(value), minValue);
  775. }
  776. catch (NumberFormatException e)
  777. {
  778. return false;
  779. }
  780. }
  781. public static boolean isValidDecimalMin(float value, float minValue)
  782. {
  783. return value >= minValue;
  784. }
  785. public static boolean isValidDecimalMin(double value, double minValue)
  786. {
  787. return value >= minValue;
  788. }
  789. public static boolean isValidDigits(BigDecimal value,
  790. int maxIntegerLength, int maxFractionLength)
  791. {
  792. int integerPartLength = value.precision() - value.scale();
  793. int fractionPartLength = value.scale() < 0 ? 0 : value.scale();
  794. return ( maxIntegerLength >= integerPartLength
  795. && maxFractionLength >= fractionPartLength );
  796. }
  797. public static boolean isValidDigits(String value,
  798. int maxIntegerLength, int maxFractionLength)
  799. {
  800. try
  801. {
  802. return isValidDigits(new BigDecimal(value), maxIntegerLength,
  803. maxFractionLength);
  804. }
  805. catch (NumberFormatException e)
  806. {
  807. return false;
  808. }
  809. }
  810. public static boolean isValidDigits(int value,
  811. int maxIntegerLength, int maxFractionLength)
  812. {
  813. return isValidDigits(new BigDecimal(value),
  814. maxIntegerLength, maxFractionLength);
  815. }
  816. public static boolean isValidDigits(long value,
  817. int maxIntegerLength, int maxFractionLength)
  818. {
  819. return isValidDigits(new BigDecimal(value),
  820. maxIntegerLength, maxFractionLength);
  821. }
  822. public static boolean isValidDigits(float value,
  823. int maxIntegerLength, int maxFractionLength)
  824. {
  825. return isValidDigits(new BigDecimal(value),
  826. maxIntegerLength, maxFractionLength);
  827. }
  828. public static boolean isValidDigits(double value,
  829. int maxIntegerLength, int maxFractionLength)
  830. {
  831. return isValidDigits(new BigDecimal(value),
  832. maxIntegerLength, maxFractionLength);
  833. }
  834. public static boolean isValidDigits(Number value,
  835. int maxIntegerLength, int maxFractionLength)
  836. {
  837. return isValidDigits(new BigDecimal(value.toString()).stripTrailingZeros(),
  838. maxIntegerLength, maxFractionLength);
  839. }
  840. public static boolean isValidEmail(CharSequence value)
  841. {
  842. return PATTERN_EMAIL.matcher(value).matches();
  843. }
  844. public static boolean isValidFutureTS(long value)
  845. {
  846. return value > System.currentTimeMillis();
  847. }
  848. public static boolean isValidFutureTS(long value, int unit, int min, int max) // already utc
  849. {
  850. final long today = System.currentTimeMillis(), multiplier;
  851. switch(unit)
  852. {
  853. case 1: // day
  854. multiplier = MILLIS_PER_DAY;
  855. break;
  856. case 2: // hour
  857. multiplier = 1000 * 60 * 60;
  858. break;
  859. case 3: // minute
  860. multiplier = 1000 * 60;
  861. break;
  862. case 4: // second
  863. multiplier = 1000;
  864. break;
  865. default: // millisecond
  866. multiplier = 1;
  867. }
  868. // no limit
  869. if(max == 0)
  870. return min == 0 ? value > today : value >= (today + (multiplier * min));
  871. return value >= (today + (multiplier * min)) &&
  872. value <= (today + (multiplier * max));
  873. }
  874. /**
  875. * Day is the unit of min and max.
  876. */
  877. public static boolean isValidFutureOrToday(long value, int min, int max) // already utc
  878. {
  879. if(0 != value % MILLIS_PER_DAY)
  880. return false;
  881. final long today = startOfTodayMS();
  882. if(value == today)
  883. return true;
  884. // no limit
  885. if(max == 0)
  886. return min == 0 ? value > today : value >= (today + (MILLIS_PER_DAY * min));
  887. return value >= (today + (MILLIS_PER_DAY * min)) &&
  888. value <= (today + (MILLIS_PER_DAY * max));
  889. }
  890. /**
  891. * Day is the unit of min and max.
  892. */
  893. public static boolean isValidFuture(long value, int min, int max) // already utc
  894. {
  895. if(0 != value % MILLIS_PER_DAY)
  896. return false;
  897. final long today = startOfTodayMS();
  898. // no limit
  899. if(max == 0)
  900. return min == 0 ? value > today : value >= (today + (MILLIS_PER_DAY * min));
  901. return value >= (today + (MILLIS_PER_DAY * min)) &&
  902. value <= (today + (MILLIS_PER_DAY * max));
  903. }
  904. public static boolean isValidFuture(Date value)
  905. {
  906. return value.after(new Date());
  907. }
  908. /*public static boolean isValidFuture(Calendar value)
  909. {
  910. return value.after(Calendar.getInstance());
  911. }*/
  912. public static boolean isValidLength(CharSequence value, int min, int max)
  913. {
  914. int length = value.length();
  915. return length >= min && length <= max;
  916. }
  917. public static boolean isValidLuhn(String value, int multiplicator)
  918. {
  919. char[] chars = value.toCharArray();
  920. // TODO use HPPC
  921. ArrayList<Integer> digits = new ArrayList<Integer>();
  922. for ( char c : chars ) {
  923. if ( Character.isDigit( c ) ) {
  924. digits.add( c - '0' );
  925. }
  926. }
  927. int length = digits.size();
  928. int sum = 0;
  929. boolean even = false;
  930. for ( int index = length - 1; index >= 0; index-- ) {
  931. int digit = digits.get( index );
  932. if ( even ) {
  933. digit *= multiplicator;
  934. }
  935. if ( digit > 9 ) {
  936. digit = digit / 10 + digit % 10;
  937. }
  938. sum += digit;
  939. even = !even;
  940. }
  941. return sum % 10 == 0;
  942. }
  943. public static boolean isValidMax(int value, int max)
  944. {
  945. return value <= max;
  946. }
  947. public static boolean isValidMax(long value, long max)
  948. {
  949. return value <= max;
  950. }
  951. public static boolean isValidMax(float value, float max)
  952. {
  953. return value <= max;
  954. }
  955. public static boolean isValidMax(double value, double max)
  956. {
  957. return value <= max;
  958. }
  959. public static boolean isValidMax(String value, long max)
  960. {
  961. try
  962. {
  963. return isValidMax(new BigDecimal(value), BigDecimal.valueOf(max));
  964. }
  965. catch(NumberFormatException e)
  966. {
  967. return false;
  968. }
  969. }
  970. public static boolean isValidMax(BigDecimal value, BigDecimal max)
  971. {
  972. return value.compareTo(max) <= 0;
  973. }
  974. public static boolean isValidMin(int value, int min)
  975. {
  976. return value >= min;
  977. }
  978. public static boolean isValidMin(long value, long min)
  979. {
  980. return value >= min;
  981. }
  982. public static boolean isValidMin(float value, float min)
  983. {
  984. return value >= min;
  985. }
  986. public static boolean isValidMin(double value, double min)
  987. {
  988. return value >= min;
  989. }
  990. public static boolean isValidMin(String value, long min)
  991. {
  992. try
  993. {
  994. return isValidMin(new BigDecimal(value), BigDecimal.valueOf(min));
  995. }
  996. catch(NumberFormatException e)
  997. {
  998. return false;
  999. }
  1000. }
  1001. public static boolean isValidMin(BigDecimal value, BigDecimal min)
  1002. {
  1003. return value.compareTo(min) >= 0;
  1004. }
  1005. public static boolean isValidGT(int value, int param)
  1006. {
  1007. return value > param;
  1008. }
  1009. public static boolean isValidGT(long value, long param)
  1010. {
  1011. return value > param;
  1012. }
  1013. public static boolean isValidGT(float value, float param)
  1014. {
  1015. return value > param;
  1016. }
  1017. public static boolean isValidGT(double value, double param)
  1018. {
  1019. return value > param;
  1020. }
  1021. public static boolean isValidGT(String value, long param)
  1022. {
  1023. try
  1024. {
  1025. return isValidGT(new BigDecimal(value), BigDecimal.valueOf(param));
  1026. }
  1027. catch(NumberFormatException e)
  1028. {
  1029. return false;
  1030. }
  1031. }
  1032. public static boolean isValidGT(BigDecimal value, BigDecimal param)
  1033. {
  1034. return value.compareTo(param) > 0;
  1035. }
  1036. // TODO isValidMax/isValidMin for BigInteger, BigDecimal and String
  1037. public static boolean isValidNotBlank(String value)
  1038. {
  1039. return value.trim().length() != 0;
  1040. }
  1041. // add-on
  1042. public static boolean isValidNotBlank(CharSequence value)
  1043. {
  1044. return value.length() != 0;
  1045. }
  1046. public static boolean isValidNotEmpty(String value)
  1047. {
  1048. return value.trim().length() != 0;
  1049. }
  1050. // add-on
  1051. public static boolean isValidNotEmpty(CharSequence value)
  1052. {
  1053. return value.length() != 0;
  1054. }
  1055. public static boolean isValidNotEmpty(CAS value)
  1056. {
  1057. return !value.isEmpty();
  1058. }
  1059. public static boolean isValidNotNull(Object value)
  1060. {
  1061. return value != null;
  1062. }
  1063. public static boolean isValidNull(Object value)
  1064. {
  1065. return value == null;
  1066. }
  1067. public static boolean isValidNotNullNotEmpty(List<?> value)
  1068. {
  1069. return value != null && !value.isEmpty();
  1070. }
  1071. public static boolean isValidPastTS(long value)
  1072. {
  1073. return value < System.currentTimeMillis();
  1074. }
  1075. public static boolean isValidPastTS(long value, int unit, int min, int max) // already utc
  1076. {
  1077. final long today = System.currentTimeMillis(), multiplier;
  1078. switch(unit)
  1079. {
  1080. case 1: // day
  1081. multiplier = MILLIS_PER_DAY;
  1082. break;
  1083. case 2: // hour
  1084. multiplier = 1000 * 60 * 60;
  1085. break;
  1086. case 3: // minute
  1087. multiplier = 1000 * 60;
  1088. break;
  1089. case 4: // second
  1090. multiplier = 1000;
  1091. break;
  1092. default: // millisecond
  1093. multiplier = 1;
  1094. }
  1095. // no limit
  1096. if(max == 0)
  1097. return min == 0 ? value < today : value <= (today - (multiplier * min));
  1098. return value <= (today - (multiplier * min)) &&
  1099. value >= (today - (multiplier * max));
  1100. }
  1101. /**
  1102. * Day is the unit of min and max.
  1103. */
  1104. public static boolean isValidPastOrToday(long value, int min, int max) // already utc
  1105. {
  1106. if(0 != value % MILLIS_PER_DAY)
  1107. return false;
  1108. final long today = startOfTodayMS();
  1109. if(value == today)
  1110. return true;
  1111. // no limit
  1112. if(max == 0)
  1113. return min == 0 ? value < today : value <= (today - (MILLIS_PER_DAY * min));
  1114. return value <= (today - (MILLIS_PER_DAY * min)) &&
  1115. value >= (today - (MILLIS_PER_DAY * max));
  1116. }
  1117. /**
  1118. * Day is the unit of min and max.
  1119. */
  1120. public static boolean isValidPast(long value, int min, int max) // already utc
  1121. {
  1122. if(0 != value % MILLIS_PER_DAY)
  1123. return false;
  1124. final long today = startOfTodayMS();
  1125. // no limit
  1126. if(max == 0)
  1127. return min == 0 ? value < today : value <= (today - (MILLIS_PER_DAY * min));
  1128. return value <= (today - (MILLIS_PER_DAY * min)) &&
  1129. value >= (today - (MILLIS_PER_DAY * max));
  1130. }
  1131. public static boolean isValidPast(Date value)
  1132. {
  1133. return value.before(new Date());
  1134. }
  1135. /*public static boolean isValidPast(Calendar value)
  1136. {
  1137. return value.before(Calendar.getInstance());
  1138. }*/
  1139. public static boolean isValidPattern(CharSequence value, Pattern pattern)
  1140. {
  1141. return pattern.matcher(value).matches();
  1142. }
  1143. public static boolean isValidSafeHtml(CharSequence value) // needs a whitelist arg
  1144. {
  1145. // TODO
  1146. return false;
  1147. }
  1148. public static boolean isValidScriptAssert(Object value)
  1149. {
  1150. // TODO
  1151. return false;
  1152. }
  1153. public static boolean isValidSize(Collection<?> collection, int min, int max)
  1154. {
  1155. int length = collection.size();
  1156. return length >= min && length <= max;
  1157. }
  1158. public static boolean isValidSize(CharSequence value, int min, int max)
  1159. {
  1160. int length = value.length();
  1161. return length >= min && length <= max;
  1162. }
  1163. public static boolean isValidSize(String value, int min, int max)
  1164. {
  1165. int length = value.trim().length();
  1166. return length >= min && length <= max;
  1167. }
  1168. // port should be passed as -1 if not configured
  1169. public static boolean isValidURL(String value, String protocol, String host, int port)
  1170. {
  1171. java.net.URL url;
  1172. try
  1173. {
  1174. url = new java.net.URL(value);
  1175. }
  1176. catch (java.net.MalformedURLException e)
  1177. {
  1178. return false;
  1179. }
  1180. if (protocol != null && protocol.length() > 0 && !url.getProtocol().equals(protocol))
  1181. {
  1182. return false;
  1183. }
  1184. if (host != null && host.length() > 0 && !url.getHost().equals(host))
  1185. {
  1186. return false;
  1187. }
  1188. if (port != -1 && url.getPort() != port)
  1189. {
  1190. return false;
  1191. }
  1192. return true;
  1193. }
  1194. public static boolean isValidRange(int value, int min, int max)
  1195. {
  1196. return isValidMin(value, min) && isValidMax(value, max);
  1197. }
  1198. public static boolean isValidRange(long value, long min, long max)
  1199. {
  1200. return isValidMin(value, min) && isValidMax(value, max);
  1201. }
  1202. public static boolean isValidRange(float value, float min, float max)
  1203. {
  1204. return isValidMin(value, min) && isValidMax(value, max);
  1205. }
  1206. public static boolean isValidRange(double value, double min, double max)
  1207. {
  1208. return isValidMin(value, min) && isValidMax(value, max);
  1209. }
  1210. public static boolean isValidRange(String value, long min, long max)
  1211. {
  1212. try
  1213. {
  1214. return isValidRange(new BigDecimal(value), BigDecimal.valueOf(min),
  1215. BigDecimal.valueOf(max));
  1216. }
  1217. catch(NumberFormatException e)
  1218. {
  1219. return false;
  1220. }
  1221. }
  1222. public static boolean isValidRange(BigDecimal value, BigDecimal min, BigDecimal max)
  1223. {
  1224. return value.compareTo(min) != -1 && value.compareTo(max) != 1;
  1225. }
  1226. public static boolean isValidCreditCardNumber(String value)
  1227. {
  1228. return isValidLuhn(value, 2);
  1229. }
  1230. }