]> git.argeo.org Git - gpl/argeo-suite.git/blob - org.argeo.app.api/src/org/argeo/app/api/IdRange.java
Adapt to changes in Argeo Commons
[gpl/argeo-suite.git] / org.argeo.app.api / src / org / argeo / app / api / IdRange.java
1 package org.argeo.app.api;
2
3 import java.util.HashSet;
4 import java.util.Set;
5 import java.util.concurrent.ThreadLocalRandom;
6
7 /** A range of numerical IDs (typically numerical uid or gid). */
8 public class IdRange {
9 // see https://systemd.io/UIDS-GIDS/#special-distribution-uid-ranges
10 final static long MIN_INCLUDED = Long.parseUnsignedLong("66000");
11 final static long MAX_EXCLUDED = Long.parseUnsignedLong("4294967294");
12
13 // We use long as a de facto unsigned int
14
15 /** included */
16 private final long min;
17 /** included */
18 private final long max;
19
20 public IdRange(long min, long max) {
21 this.min = min;
22 this.max = max;
23 }
24
25 public IdRange(long minPow10) {
26 this(minPow10, maxFromMinPow10(minPow10));
27 }
28
29 public long getMin() {
30 return min;
31 }
32
33 public long getMax() {
34 return max;
35 }
36
37 @Override
38 public int hashCode() {
39 return (int) min;
40 }
41
42 @Override
43 public boolean equals(Object obj) {
44 if (obj instanceof IdRange idRange) {
45 return min == idRange.min && max == idRange.max;
46 } else
47 return false;
48 }
49
50 @Override
51 public String toString() {
52 return "[" + Long.toUnsignedString(min) + "," + Long.toUnsignedString(max) + "]";
53 }
54
55 /*
56 * RANGE GENERATION
57 */
58 public static synchronized Set<IdRange> randomRanges10000(int count, Set<IdRange> forbiddenRanges) {
59 Set<IdRange> res = new HashSet<>();
60
61 for (int i = 0; i < count; i++) {
62 IdRange newRange = null;
63 do {
64 newRange = randomRange10000();
65 } while (overlap(newRange, res) || overlap(newRange, forbiddenRanges));
66 res.add(newRange);
67 }
68 return res;
69 }
70
71 public static synchronized IdRange randomRange10000() {
72 // TODO make it more generic
73 long minPred = 7l;
74 long maxPred = 429496l;
75
76 long rand = ThreadLocalRandom.current().nextLong(minPred, maxPred);
77 long min = rand * 10000l;
78 return new IdRange(min);
79 }
80
81 public static boolean overlap(IdRange idRange, Set<IdRange> idRanges) {
82 for (IdRange other : idRanges) {
83 if (overlap(idRange, other))
84 return true;
85 }
86 return false;
87 }
88
89 public static boolean overlap(IdRange idRange, IdRange other) {
90 // see
91 // https://stackoverflow.com/questions/3269434/whats-the-most-efficient-way-to-test-if-two-ranges-overlap
92 return idRange.min <= other.max && other.min <= idRange.max;
93 }
94
95 /*
96 * UTILITIES
97 */
98
99 private static long maxFromMinPow10(long minPow10) {
100 if ((minPow10 % 100) != 0) {
101 throw new IllegalArgumentException(minPow10 + " must at least ends with two zeroes");
102 }
103 int exp = 2;
104 exp: for (int i = exp + 1; i < 10; i++) {
105 if ((minPow10 % pow10(i)) != 0)
106 break exp;
107 exp++;
108 }
109 // System.out.println(exp);
110
111 long max = minPow10 + pow10(exp) - 1;
112 return max;
113 }
114
115 /** Power of 10. */
116 private static long pow10(int exp) {
117 if (exp == 0)
118 return 1;
119 else
120 return 10 * pow10(exp - 1);
121 }
122
123 public static void main(String... args) {
124 System.out.println(maxFromMinPow10(100));
125 System.out.println(maxFromMinPow10(78500));
126 System.out.println(maxFromMinPow10(716850000));
127
128 // System.out.println(pow10(6));
129 // System.out.println(maxFromMinPow10(12));
130 // System.out.println(maxFromMinPow10(124));
131 // System.out.println(maxFromMinPow10(99814565));
132 }
133 }