Skip to content

Commit b518e21

Browse files
authored
Merge pull request #92 from ie3-institute/ck/#91-namingConventionUtils
Add a class that aids in providing namings in different naming conventions
2 parents 46fc9a5 + 6a9b9fc commit b518e21

File tree

7 files changed

+714
-17
lines changed

7 files changed

+714
-17
lines changed

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased/Snapshot]
88

9+
## [1.5.2]
10+
### Changed
11+
- Use Maven Central as repository for dependencies
12+
13+
### Added
14+
- `Naming` that aids in providing an entity naming respecting different well known naming strategies
15+
916
## [1.5.1]
1017
### Fixed
1118
- Malicious implementation of some units + additional tests for transformed units
@@ -61,7 +68,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6168
### Fixed
6269
- fixes + extensions in StandardUnits
6370

64-
[Unreleased/Snapshot]: https://github.com/ie3-institute/powersystemutils/compare/v1.5.1...HEAD
71+
[Unreleased/Snapshot]: https://github.com/ie3-institute/powersystemutils/compare/v1.5.2...HEAD
72+
[1.5.2]: https://github.com/ie3-institute/powersystemutils/compare/v1.4...v1.5.2
6573
[1.5.1]: https://github.com/ie3-institute/powersystemutils/compare/v1.4...v1.5.1
6674
[1.5]: https://github.com/ie3-institute/powersystemutils/compare/v1.4...v1.5
6775
[1.4]: https://github.com/ie3-institute/powersystemutils/compare/v1.3.2...v1.4

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ ext {
2020
}
2121

2222
group = 'com.github.ie3-institute'
23-
version = '1.6-SNAPSHOT'
23+
version = '1.5.2'
2424
description = 'PowerSystemUtils'
2525
sourceCompatibility = javaVersion
2626
targetCompatibility = javaVersion
@@ -37,7 +37,7 @@ apply from: scriptsLocation + 'mavenCentralPublish.gradle'
3737

3838

3939
repositories {
40-
jcenter()
40+
mavenCentral()
4141
maven { url = "https://www.jitpack.io" } // allows for github repos as dependencies
4242
}
4343

src/main/java/edu/ie3/util/StringUtils.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,15 @@ private static boolean needsCsvRFC4180Quote(String inputString, String csvSep) {
147147
|| inputString.contains("\"")
148148
|| inputString.contains("\n");
149149
}
150+
151+
/**
152+
* Capitalizes a given String.
153+
*
154+
* @param inputString The String that is given.
155+
* @return The String, that is taken
156+
*/
157+
public static String capitalize(String inputString) {
158+
if (inputString.isEmpty()) return inputString;
159+
else return inputString.substring(0, 1).toUpperCase() + inputString.substring(1);
160+
}
150161
}
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
/*
2+
* © 2021. TU Dortmund University,
3+
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
4+
* Research group Distribution grid planning and operation
5+
*/
6+
package edu.ie3.util.naming;
7+
8+
import edu.ie3.util.StringUtils;
9+
import java.util.Arrays;
10+
import java.util.LinkedList;
11+
import java.util.Objects;
12+
import java.util.stream.Collectors;
13+
14+
public class Naming {
15+
private static final String DELIMITER_REGEX = "[_\\-|]";
16+
17+
/**
18+
* Builds a naming from a collection of single words. We assume, that all words are yet
19+
* de-composed. This means, they only comply with {@link NamingConvention#FLAT}. Components, that
20+
* contain one of the known delimiters (_, -, |) are neglected.
21+
*
22+
* @param singleWords The single words, which shall compose the naming later
23+
* @return Proper naming object
24+
*/
25+
public static Naming from(String... singleWords) {
26+
/* Go through all single words, make them lower case and filter out those, that contain one of known delimiters */
27+
LinkedList<String> components =
28+
Arrays.stream(singleWords)
29+
.map(String::toLowerCase)
30+
.filter(entry -> !entry.matches(".*" + DELIMITER_REGEX + ".*"))
31+
.collect(Collectors.toCollection(LinkedList::new));
32+
33+
String flatCase = String.join("", components);
34+
String upperFlatCase =
35+
components.stream().map(String::toUpperCase).collect(Collectors.joining(""));
36+
String camelCase = String.join("", camelCasing(components));
37+
String pascalCase =
38+
components.stream().map(StringUtils::capitalize).collect(Collectors.joining(""));
39+
String snakeCase = String.join("_", components);
40+
String screamingSnakeCase =
41+
components.stream().map(String::toUpperCase).collect(Collectors.joining("_"));
42+
String camelSnakeCase = String.join("_", camelCasing(components));
43+
String pascalSnakeCase =
44+
components.stream().map(StringUtils::capitalize).collect(Collectors.joining("_"));
45+
String kebabCase = String.join("-", components);
46+
String donerCase = String.join("|", components);
47+
String screamingKebabCase =
48+
components.stream().map(String::toUpperCase).collect(Collectors.joining("-"));
49+
String trainCase =
50+
components.stream().map(StringUtils::capitalize).collect(Collectors.joining("-"));
51+
52+
return new Naming(
53+
flatCase,
54+
upperFlatCase,
55+
camelCase,
56+
pascalCase,
57+
snakeCase,
58+
screamingSnakeCase,
59+
camelSnakeCase,
60+
pascalSnakeCase,
61+
kebabCase,
62+
donerCase,
63+
screamingKebabCase,
64+
trainCase);
65+
}
66+
67+
/**
68+
* Adjust the case of the first letter of each component to comply with the rules of camel casing:
69+
*
70+
* <ul>
71+
* <li>The first letter is always small case
72+
* <li>A letter, that follows a digit is always small case
73+
* <li>A letter, that follows a single letter component is always small case
74+
* <li>All other first letters are upper case
75+
* </ul>
76+
*
77+
* @param components The small case components
78+
* @return A {@link LinkedList} with properly capitalized components
79+
*/
80+
private static LinkedList<String> camelCasing(LinkedList<String> components) {
81+
LinkedList<String> output = new LinkedList<>();
82+
83+
/* The first letter is always not capitalized */
84+
boolean blockCapitalization = true;
85+
for (String component : components) {
86+
output.add(blockCapitalization ? component : StringUtils.capitalize(component));
87+
/* The next component is not capitalized, if the last one ends with a digit or is only one character */
88+
blockCapitalization = component.matches("\\d$") || component.length() == 1;
89+
}
90+
return output;
91+
}
92+
93+
private final String flatCase;
94+
private final String upperFlatCase;
95+
private final String camelCase;
96+
private final String pascalCase;
97+
private final String snakeCase;
98+
private final String screamingSnakeCase;
99+
private final String camelSnakeCase;
100+
private final String pascalSnakeCase;
101+
private final String kebabCase;
102+
private final String donerCase;
103+
private final String screamingKebabCase;
104+
private final String trainCase;
105+
106+
private Naming(
107+
String flatCase,
108+
String upperFlatCase,
109+
String camelCase,
110+
String pascalCase,
111+
String snakeCase,
112+
String screamingSnakeCase,
113+
String camelSnakeCase,
114+
String pascalSnakeCase,
115+
String kebabCase,
116+
String donerCase,
117+
String screamingKebabCase,
118+
String trainCase) {
119+
this.flatCase = flatCase;
120+
this.upperFlatCase = upperFlatCase;
121+
this.camelCase = camelCase;
122+
this.pascalCase = pascalCase;
123+
this.snakeCase = snakeCase;
124+
this.screamingSnakeCase = screamingSnakeCase;
125+
this.camelSnakeCase = camelSnakeCase;
126+
this.pascalSnakeCase = pascalSnakeCase;
127+
this.kebabCase = kebabCase;
128+
this.donerCase = donerCase;
129+
this.screamingKebabCase = screamingKebabCase;
130+
this.trainCase = trainCase;
131+
}
132+
133+
public String flatCase() {
134+
return flatCase;
135+
}
136+
137+
public String upperFlatCase() {
138+
return upperFlatCase;
139+
}
140+
141+
public String camelCase() {
142+
return camelCase;
143+
}
144+
145+
public String pascalCase() {
146+
return pascalCase;
147+
}
148+
149+
public String snakeCase() {
150+
return snakeCase;
151+
}
152+
153+
public String screamingSnakeCase() {
154+
return screamingSnakeCase;
155+
}
156+
157+
public String camelSnakeCase() {
158+
return camelSnakeCase;
159+
}
160+
161+
public String pascalSnakeCase() {
162+
return pascalSnakeCase;
163+
}
164+
165+
public String kebabCase() {
166+
return kebabCase;
167+
}
168+
169+
public String donerCase() {
170+
return donerCase;
171+
}
172+
173+
public String screamingKebabCase() {
174+
return screamingKebabCase;
175+
}
176+
177+
public String trainCase() {
178+
return trainCase;
179+
}
180+
181+
/**
182+
* Get the naming as the given convention.
183+
*
184+
* @param convention The desired convention
185+
* @return The naming
186+
*/
187+
public String as(NamingConvention convention) {
188+
switch (convention) {
189+
case FLAT:
190+
return flatCase();
191+
case CAMEL:
192+
return camelCase();
193+
case DONER:
194+
return donerCase();
195+
case KEBAB:
196+
return kebabCase();
197+
case SNAKE:
198+
return snakeCase();
199+
case TRAIN:
200+
return trainCase();
201+
case PASCAL:
202+
return pascalCase();
203+
case UPPER_FLAT:
204+
return upperFlatCase();
205+
case CAMEL_SNAKE:
206+
return camelSnakeCase();
207+
case PASCAL_SNAKE:
208+
return pascalSnakeCase();
209+
case SCREAMING_KEBAB:
210+
return screamingKebabCase();
211+
case SCREAMING_SNAKE:
212+
return screamingSnakeCase();
213+
default:
214+
throw new IllegalArgumentException(
215+
"The naming convention '"
216+
+ convention
217+
+ "', you requested, is currently not supported.");
218+
}
219+
}
220+
221+
@Override
222+
public boolean equals(Object o) {
223+
if (this == o) return true;
224+
if (!(o instanceof Naming)) return false;
225+
Naming naming = (Naming) o;
226+
return flatCase.equals(naming.flatCase)
227+
&& upperFlatCase.equals(naming.upperFlatCase)
228+
&& camelCase.equals(naming.camelCase)
229+
&& pascalCase.equals(naming.pascalCase)
230+
&& snakeCase.equals(naming.snakeCase)
231+
&& screamingSnakeCase.equals(naming.screamingSnakeCase)
232+
&& camelSnakeCase.equals(naming.camelSnakeCase)
233+
&& pascalSnakeCase.equals(naming.pascalSnakeCase)
234+
&& kebabCase.equals(naming.kebabCase)
235+
&& donerCase.equals(naming.donerCase)
236+
&& screamingKebabCase.equals(naming.screamingKebabCase)
237+
&& trainCase.equals(naming.trainCase);
238+
}
239+
240+
@Override
241+
public int hashCode() {
242+
return Objects.hash(
243+
flatCase,
244+
upperFlatCase,
245+
camelCase,
246+
pascalCase,
247+
snakeCase,
248+
screamingSnakeCase,
249+
camelSnakeCase,
250+
pascalSnakeCase,
251+
kebabCase,
252+
donerCase,
253+
screamingKebabCase,
254+
trainCase);
255+
}
256+
257+
@Override
258+
public String toString() {
259+
return "Naming{" + "camelCase='" + camelCase + '\'' + '}';
260+
}
261+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* © 2021. TU Dortmund University,
3+
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
4+
* Research group Distribution grid planning and operation
5+
*/
6+
package edu.ie3.util.naming;
7+
8+
/**
9+
* An enumeration of commonly known and used naming conventions according to Wikipedia.
10+
*
11+
* @see <a href="https://en.wikipedia.org/wiki/Naming_convention_(programming)">this Wikipedia
12+
* article</a>
13+
*/
14+
public enum NamingConvention {
15+
FLAT,
16+
UPPER_FLAT,
17+
CAMEL,
18+
PASCAL,
19+
SNAKE,
20+
SCREAMING_SNAKE,
21+
CAMEL_SNAKE,
22+
PASCAL_SNAKE,
23+
KEBAB,
24+
DONER,
25+
SCREAMING_KEBAB,
26+
TRAIN
27+
}

src/test/groovy/edu/ie3/util/StringUtilsTest.groovy

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -302,19 +302,35 @@ class StringUtilsTest extends Specification {
302302
StringUtils.csvString(inputString, csvSep) == expect
303303

304304
where:
305-
inputString | csvSep || expect
306-
"activePowerGradient" | "," || "activePowerGradient"
307-
"\"100,0\"" | "," || "\"100,0\""
308-
"100,0" | "," || "\"100,0\""
309-
"100,0" | ";" || "\"100,0\""
310-
"100;0" | ";" || "\"100;0\""
311-
"\"100;0\"" | ";" || "\"100;0\""
312-
"100;0" | "," || "100;0"
313-
"olm:{(0.00,1.00)}" | "," || "\"olm:{(0.00,1.00)}\""
314-
"olm:{(0.00,1.00)}" | ";" || "\"olm:{(0.00,1.00)}\""
315-
"{\"type\":\"Point\",\"coordinates\":[7.411111,51.492528]}" | "," || "\"{\"\"type\"\":\"\"Point\"\",\"\"coordinates\"\":[7.411111,51.492528]}\""
316-
"{\"type\":\"Point\",\"coordinates\":[7.411111,51.492528]}" | ";" || "\"{\"\"type\"\":\"\"Point\"\",\"\"coordinates\"\":[7.411111,51.492528]}\""
317-
"uu,id" | "," || "\"uu,id\""
318-
"uu,id" | ";" || "\"uu,id\""
305+
inputString | csvSep || expect
306+
"activePowerGradient" | "," || "activePowerGradient"
307+
"\"100,0\"" | "," || "\"100,0\""
308+
"100,0" | "," || "\"100,0\""
309+
"100,0" | ";" || "\"100,0\""
310+
"100;0" | ";" || "\"100;0\""
311+
"\"100;0\"" | ";" || "\"100;0\""
312+
"100;0" | "," || "100;0"
313+
"olm:{(0.00,1.00)}" | "," || "\"olm:{(0.00,1.00)}\""
314+
"olm:{(0.00,1.00)}" | ";" || "\"olm:{(0.00,1.00)}\""
315+
"{\"type\":\"Point\",\"coordinates\":[7.411111,51.492528]}" | "," || "\"{\"\"type\"\":\"\"Point\"\",\"\"coordinates\"\":[7.411111,51.492528]}\""
316+
"{\"type\":\"Point\",\"coordinates\":[7.411111,51.492528]}" | ";" || "\"{\"\"type\"\":\"\"Point\"\",\"\"coordinates\"\":[7.411111,51.492528]}\""
317+
"uu,id" | "," || "\"uu,id\""
318+
"uu,id" | ";" || "\"uu,id\""
319+
}
320+
321+
def "The StringUtils are able to capitalize a String correctly"() {
322+
expect:
323+
StringUtils.capitalize(inputString) == expected
324+
325+
where:
326+
inputString || expected
327+
"" || ""
328+
"a" || "A"
329+
"A" || "A"
330+
"hello" || "Hello"
331+
"Hello" || "Hello"
332+
"helloWorld" || "HelloWorld"
333+
"HelloWorld" || "HelloWorld"
334+
"2" || "2"
319335
}
320336
}

0 commit comments

Comments
 (0)