]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.api.acr/src/org/argeo/api/acr/CompositeString.java
Experiment with package level A2 metadata
[lgpl/argeo-commons.git] / org.argeo.api.acr / src / org / argeo / api / acr / CompositeString.java
1 package org.argeo.api.acr;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.List;
6 import java.util.Objects;
7 import java.util.StringTokenizer;
8
9 /** A name that can be expressed with various conventions. */
10 public class CompositeString {
11 public final static Character UNDERSCORE = Character.valueOf('_');
12 public final static Character SPACE = Character.valueOf(' ');
13 public final static Character DASH = Character.valueOf('-');
14
15 private final String[] parts;
16
17 // optimisation
18 private final int hashCode;
19
20 public CompositeString(String str) {
21 Objects.requireNonNull(str, "String cannot be null");
22 if ("".equals(str.trim()))
23 throw new IllegalArgumentException("String cannot be empty");
24 if (!str.equals(str.trim()))
25 throw new IllegalArgumentException("String must be trimmed");
26 this.parts = toParts(str);
27 hashCode = hashCode(this.parts);
28 }
29
30 public String toString(char separator, boolean upperCase) {
31 StringBuilder sb = null;
32 for (String part : parts) {
33 if (sb == null) {
34 sb = new StringBuilder();
35 } else {
36 sb.append(separator);
37 }
38 sb.append(upperCase ? part.toUpperCase() : part);
39 }
40 return sb.toString();
41 }
42
43 public String toStringCaml(boolean firstCharUpperCase) {
44 StringBuilder sb = null;
45 for (String part : parts) {
46 if (sb == null) {// first
47 sb = new StringBuilder();
48 sb.append(firstCharUpperCase ? Character.toUpperCase(part.charAt(0)) : part.charAt(0));
49 } else {
50 sb.append(Character.toUpperCase(part.charAt(0)));
51 }
52
53 if (part.length() > 1)
54 sb.append(part.substring(1));
55 }
56 return sb.toString();
57 }
58
59 @Override
60 public int hashCode() {
61 return hashCode;
62 }
63
64 @Override
65 public boolean equals(Object obj) {
66 if (obj == null || !(obj instanceof CompositeString))
67 return false;
68
69 CompositeString other = (CompositeString) obj;
70 return Arrays.equals(parts, other.parts);
71 }
72
73 @Override
74 public String toString() {
75 return toString(DASH, false);
76 }
77
78 public static String[] toParts(String str) {
79 Character separator = null;
80 if (str.indexOf(UNDERSCORE) >= 0) {
81 checkNo(str, SPACE);
82 checkNo(str, DASH);
83 separator = UNDERSCORE;
84 } else if (str.indexOf(DASH) >= 0) {
85 checkNo(str, SPACE);
86 checkNo(str, UNDERSCORE);
87 separator = DASH;
88 } else if (str.indexOf(SPACE) >= 0) {
89 checkNo(str, DASH);
90 checkNo(str, UNDERSCORE);
91 separator = SPACE;
92 }
93
94 List<String> res = new ArrayList<>();
95 if (separator != null) {
96 StringTokenizer st = new StringTokenizer(str, separator.toString());
97 while (st.hasMoreTokens()) {
98 res.add(st.nextToken().toLowerCase());
99 }
100 } else {
101 // single
102 String strLowerCase = str.toLowerCase();
103 if (str.toUpperCase().equals(str) || strLowerCase.equals(str))
104 return new String[] { strLowerCase };
105
106 // CAML
107 StringBuilder current = null;
108 for (char c : str.toCharArray()) {
109 if (Character.isUpperCase(c)) {
110 if (current != null)
111 res.add(current.toString());
112 current = new StringBuilder();
113 }
114 if (current == null)// first char is lower case
115 current = new StringBuilder();
116 current.append(Character.toLowerCase(c));
117 }
118 res.add(current.toString());
119 }
120 return res.toArray(new String[res.size()]);
121 }
122
123 private static void checkNo(String str, Character c) {
124 if (str.indexOf(c) >= 0) {
125 throw new IllegalArgumentException("Only one kind of sperator is allowed");
126 }
127 }
128
129 private static int hashCode(String[] parts) {
130 int hashCode = 0;
131 for (String part : parts) {
132 hashCode = hashCode + part.hashCode();
133 }
134 return hashCode;
135 }
136
137 static boolean smokeTests() {
138 CompositeString plainName = new CompositeString("NAME");
139 assert "name".equals(plainName.toString());
140 assert "NAME".equals(plainName.toString(UNDERSCORE, true));
141 assert "name".equals(plainName.toString(UNDERSCORE, false));
142 assert "name".equals(plainName.toStringCaml(false));
143 assert "Name".equals(plainName.toStringCaml(true));
144
145 CompositeString camlName = new CompositeString("myComplexName");
146
147 assert new CompositeString("my-complex-name").equals(camlName);
148 assert new CompositeString("MY_COMPLEX_NAME").equals(camlName);
149 assert new CompositeString("My complex Name").equals(camlName);
150 assert new CompositeString("MyComplexName").equals(camlName);
151
152 assert "my-complex-name".equals(camlName.toString());
153 assert "MY_COMPLEX_NAME".equals(camlName.toString(UNDERSCORE, true));
154 assert "my_complex_name".equals(camlName.toString(UNDERSCORE, false));
155 assert "myComplexName".equals(camlName.toStringCaml(false));
156 assert "MyComplexName".equals(camlName.toStringCaml(true));
157
158 return CompositeString.class.desiredAssertionStatus();
159 }
160
161 public static void main(String[] args) {
162 System.out.println(smokeTests());
163 }
164 }