1 package org.opendaylight.yangtools.binding.generator.util;
3 import java.text.DateFormat;
4 import java.text.SimpleDateFormat;
5 import java.util.Arrays;
6 import java.util.HashSet;
10 import org.opendaylight.yangtools.yang.common.QName;
11 import org.opendaylight.yangtools.yang.model.api.Module;
12 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
13 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
16 * Contains the methods for converting strings to valid JAVA language strings
17 * (package names, class names, attribute names).
21 public final class BindingGeneratorUtil {
23 private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyMMdd");
26 * Array of strings values which represents JAVA reserved words.
28 private static final String[] SET_VALUES = new String[] { "abstract", "assert", "boolean", "break", "byte", "case",
29 "catch", "char", "class", "const", "continue", "default", "double", "do", "else", "enum", "extends",
30 "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int",
31 "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return",
32 "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient",
33 "true", "try", "void", "volatile", "while" };
36 * Impossible to instantiate this class. All of the methods or attributes
39 private BindingGeneratorUtil() {
43 * Hash set of words which are reserved in JAVA language.
45 private static final Set<String> JAVA_RESERVED_WORDS = new HashSet<String>(Arrays.asList(SET_VALUES));
48 * Converts string <code>packageName</code> to valid JAVA package name.
50 * If some words of package name are digits of JAVA reserved words they are
51 * prefixed with underscore character.
54 * string which contains words separated by point.
55 * @return package name which contains words separated by point.
57 private static String validateJavaPackage(final String packageName) {
58 if (packageName != null) {
59 final String[] packNameParts = packageName.split("\\.");
60 if (packNameParts != null) {
61 final StringBuilder builder = new StringBuilder();
62 for (int i = 0; i < packNameParts.length; ++i) {
63 final String packNamePart = packNameParts[i];
64 if (Character.isDigit(packNamePart.charAt(0))) {
65 packNameParts[i] = "_" + packNamePart;
66 } else if (JAVA_RESERVED_WORDS.contains(packNamePart)) {
67 packNameParts[i] = "_" + packNamePart;
72 builder.append(packNameParts[i]);
74 return builder.toString();
81 * Converts <code>parameterName</code> to valid JAVA parameter name.
83 * If the <code>parameterName</code> is one of the JAVA reserved words then
84 * it is prefixed with underscore character.
86 * @param parameterName
87 * string with the parameter name
88 * @return string with the admissible parameter name
90 public static String resolveJavaReservedWordEquivalency(final String parameterName) {
91 if (parameterName != null && JAVA_RESERVED_WORDS.contains(parameterName)) {
92 return "_" + parameterName;
98 * Converts module name to valid JAVA package name.
100 * The package name consists of:
102 * <li>prefix - <i>org.opendaylight.yang.gen.v</i></li>
103 * <li>module YANG version - <i>org.opendaylight.yang.gen.v</i></li>
104 * <li>module namespace - invalid characters are replaced with dots</li>
105 * <li>revision prefix - <i>.rev</i></li>
106 * <li>revision - YYYYMMDD (MM and DD aren't spread to the whole length)</li>
110 * module which contains data about namespace and revision date
111 * @return string with the valid JAVA package name
112 * @throws IllegalArgumentException
113 * if the revision date of the <code>module</code> equals
116 public static String moduleNamespaceToPackageName(final Module module) {
117 final StringBuilder packageNameBuilder = new StringBuilder();
119 if (module.getRevision() == null) {
120 throw new IllegalArgumentException("Module " + module.getName() + " does not specify revision date!");
122 packageNameBuilder.append("org.opendaylight.yang.gen.v");
123 packageNameBuilder.append(module.getYangVersion());
124 packageNameBuilder.append(".");
126 String namespace = module.getNamespace().toString();
127 namespace = namespace.replace("://", ".");
128 namespace = namespace.replace("/", ".");
129 namespace = namespace.replace(":", ".");
130 namespace = namespace.replace("-", ".");
131 namespace = namespace.replace("@", ".");
132 namespace = namespace.replace("$", ".");
133 namespace = namespace.replace("#", ".");
134 namespace = namespace.replace("'", ".");
135 namespace = namespace.replace("*", ".");
136 namespace = namespace.replace("+", ".");
137 namespace = namespace.replace(",", ".");
138 namespace = namespace.replace(";", ".");
139 namespace = namespace.replace("=", ".");
141 packageNameBuilder.append(namespace);
142 packageNameBuilder.append(".rev");
143 packageNameBuilder.append(DATE_FORMAT.format(module.getRevision()));
145 return validateJavaPackage(packageNameBuilder.toString());
149 * Creates package name from specified <code>basePackageName</code> (package
150 * name for module) and <code>schemaPath</code>.
152 * Resulting package name is concatenation of <code>basePackageName</code>
153 * and all local names of YANG nodes which are parents of some node for
154 * which <code>schemaPath</code> is specified.
156 * @param basePackageName
157 * string with package name of the module
159 * list of names of YANG nodes which are parents of some node +
161 * @return string with valid JAVA package name
163 public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) {
164 if (basePackageName == null) {
165 throw new IllegalArgumentException("Base Package Name cannot be NULL!");
167 if (schemaPath == null) {
168 throw new IllegalArgumentException("Schema Path cannot be NULL!");
171 final StringBuilder builder = new StringBuilder();
172 builder.append(basePackageName);
173 final List<QName> pathToNode = schemaPath.getPath();
174 final int traversalSteps = (pathToNode.size() - 1);
175 for (int i = 0; i < traversalSteps; ++i) {
177 String nodeLocalName = pathToNode.get(i).getLocalName();
179 nodeLocalName = nodeLocalName.replace(":", ".");
180 nodeLocalName = nodeLocalName.replace("-", ".");
181 builder.append(nodeLocalName);
183 return validateJavaPackage(builder.toString());
187 * Generates the package name for type definition from
188 * <code>typeDefinition</code> and <code>basePackageName</code>.
190 * @param basePackageName
191 * string with the package name of the module
192 * @param typeDefinition
193 * type definition for which the package name will be generated *
194 * @return string with valid JAVA package name
195 * @throws IllegalArgumentException
197 * <li>if <code>basePackageName</code> equals <code>null</code></li>
198 * <li>if <code>typeDefinition</code> equals <code>null</code></li>
201 public static String packageNameForTypeDefinition(final String basePackageName,
202 final TypeDefinition<?> typeDefinition) {
203 if (basePackageName == null) {
204 throw new IllegalArgumentException("Base Package Name cannot be NULL!");
206 if (typeDefinition == null) {
207 throw new IllegalArgumentException("Type Definition reference cannot be NULL!");
210 final StringBuilder builder = new StringBuilder();
211 builder.append(basePackageName);
212 return validateJavaPackage(builder.toString());
216 * Converts <code>token</code> to string which is in accordance with best
217 * practices for JAVA class names.
220 * string which contains characters which should be converted to
222 * @return string which is in accordance with best practices for JAVA class
225 public static String parseToClassName(String token) {
226 return parseToCamelCase(token, true);
230 * Converts <code>token</code> to string which is in accordance with best
231 * practices for JAVA parameter names.
234 * string which contains characters which should be converted to
235 * JAVA parameter name
236 * @return string which is in accordance with best practices for JAVA
239 public static String parseToValidParamName(final String token) {
240 return resolveJavaReservedWordEquivalency(parseToCamelCase(token, false));
245 * Converts string <code>token</code> to the cammel case format.
248 * string which should be converted to the cammel case format
250 * boolean value which says whether the first character of the
251 * <code>token</code> should|shuldn't be uppercased
252 * @return string in the cammel case format
253 * @throws IllegalArgumentException
255 * <li>if <code>token</code> without white spaces is empty</li>
256 * <li>if <code>token</code> equals null</li>
260 private static String parseToCamelCase(final String token, final boolean uppercase) {
262 throw new IllegalArgumentException("Name can not be null");
265 String correctStr = token.trim();
266 correctStr = correctStr.replace(".", "");
268 if (correctStr.isEmpty()) {
269 throw new IllegalArgumentException("Name can not be emty");
272 correctStr = replaceWithCamelCase(correctStr, ' ');
273 correctStr = replaceWithCamelCase(correctStr, '-');
274 correctStr = replaceWithCamelCase(correctStr, '_');
276 String firstChar = correctStr.substring(0, 1);
278 firstChar = firstChar.toUpperCase();
280 firstChar = firstChar.toLowerCase();
283 if (firstChar.matches("[0-9]")) {
284 correctStr = "_" + correctStr;
286 correctStr = firstChar + correctStr.substring(1);
292 * Replaces all the occurances of the <code>removalChar</code> in the
293 * <code>text</code> with empty string and converts following character to
297 * string with source text which should be converted
299 * character which is sought in the <code>text</code>
300 * @return string which doesn't contain <code>removalChar</code> and has
301 * following characters converted to upper case
302 * @throws IllegalArgumentException
303 * if the length of the returning string has length 0
305 private static String replaceWithCamelCase(String text, char removalChar) {
306 StringBuilder sb = new StringBuilder(text);
307 String toBeRemoved = String.valueOf(removalChar);
309 int toBeRemovedPos = sb.indexOf(toBeRemoved);
310 while (toBeRemovedPos != -1) {
311 sb.replace(toBeRemovedPos, toBeRemovedPos + 1, "");
312 // check if 'toBeRemoved' character is not the only character in
314 if (sb.length() == 0) {
315 throw new IllegalArgumentException("The resulting string can not be empty");
317 String replacement = String.valueOf(sb.charAt(toBeRemovedPos)).toUpperCase();
318 sb.setCharAt(toBeRemovedPos, replacement.charAt(0));
319 toBeRemovedPos = sb.indexOf(toBeRemoved);
321 return sb.toString();