NameHandler.java
package de.r3s6.maven.constcreator;
/*
* Copyright 2023 Ralf Schandl
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
/**
* Utilities class with name-related methods.
*
* @author Ralf Schandl
*/
public final class NameHandler {
private static final String DIV = "_";
private static final char DIV_CHR = '_';
private NameHandler() {
// Nothing to instantiate.
}
/**
* Creates a java constant, variable and getter name from the given name.
* <p>
* The given name is split into parts at lower-upper change, underscore and
* non-identifier chars. The parts are then combined into new names suitable for
* a java constant, variable or getter-method.
*
* @param name the initial name (aka property key)
*
* @return {@link JavaNames} containing names
* @throws IllegalArgumentException if name is empty String
* @throws NullPointerException if name is null
*/
public static JavaNames createJavaNames(final String name) {
final List<String> np = splitParts(name);
return new JavaNames(buildConstantName(np), buildVariableName(np), buildGetterName(np));
}
/**
* Build a class name for the given name.
*
* @param name the name to build a class name
* @return a java class name
* @throws IllegalArgumentException if name is empty String
* @throws NullPointerException if name is null
*/
public static String createTypeName(final String name) {
final String typename = camelCase(splitParts(name));
if (Character.isJavaIdentifierStart(typename.charAt(0))) {
return typename;
} else {
return DIV + typename;
}
}
/**
* Splits the name into parts at lower-upper change, underscore and
* non-identifier chars.
*
* @param name the name to split.
* @return a list of name parts, all lower case
*/
private static List<String> splitParts(final String name) {
Objects.requireNonNull(name, "name must not be null");
if (name.length() == 0) {
throw new IllegalArgumentException("name must not be empty");
}
final List<String> parts = new ArrayList<>();
final StringBuilder sb = new StringBuilder();
boolean lastIsLower = false;
for (char chr : name.toCharArray()) {
final boolean isUpper = Character.isUpperCase(chr);
if (chr != DIV_CHR && Character.isJavaIdentifierPart(chr)) {
if (lastIsLower && isUpper) {
parts.add(sb.toString().toLowerCase(Locale.US));
sb.setLength(0);
}
sb.append(chr);
lastIsLower = !isUpper;
} else if (sb.length() > 0) {
parts.add(sb.toString().toLowerCase(Locale.US));
sb.setLength(0);
lastIsLower = false;
}
}
if (sb.length() > 0) {
parts.add(sb.toString().toLowerCase(Locale.US));
}
if (parts.isEmpty()) {
final char[] fake = new char[name.length()];
Arrays.fill(fake, '_');
parts.add(new String(fake)); // NOCS: IllegalInstantiation
}
return parts;
}
/**
* Concatenate parts with underscore and make it upper-case.
*
* @param parts parts to concatenate
* @return name suitable as Java constant name
*/
private static String buildConstantName(final List<String> parts) {
final String name = String.join(DIV, parts).toUpperCase(Locale.US);
if (Character.isJavaIdentifierStart(name.charAt(0))) {
return name;
} else {
return DIV + name;
}
}
/**
* Concatenate parts lower-camel-case.
*
* @param parts parts to concatenate
* @return name suitable as Java variable name
*/
private static String buildVariableName(final List<String> parts) {
String name = camelCase(parts);
name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
if (Character.isJavaIdentifierStart(name.charAt(0))) {
return name;
} else {
return DIV + name;
}
}
/**
* Concatenate parts camel-case with leading "get".
*
* @param parts parts to concatenate
* @return name suitable as Java getter method name
*/
private static String buildGetterName(final List<String> parts) {
return "get" + camelCase(parts);
}
private static String camelCase(final List<String> parts) {
final StringBuilder sb = new StringBuilder();
for (String part : parts) {
sb.append(Character.toUpperCase(part.charAt(0)));
sb.append(part.substring(1).toLowerCase());
}
return sb.toString();
}
/**
* Provides different name types created from a property key.
*/
public static final class JavaNames {
private final String constantName;
private final String variableName;
private final String getterName;
private JavaNames(final String constantName, final String variableName, final String getterName) {
this.constantName = constantName;
this.variableName = variableName;
this.getterName = getterName;
}
public String getConstantName() {
return constantName;
}
public String getVariableName() {
return variableName;
}
public String getGetterName() {
return getterName;
}
}
}