Fix checkstyle in mdsal-binding2-generator-util
[mdsal.git] / binding2 / mdsal-binding2-generator-util / src / main / java / org / opendaylight / mdsal / binding / javav2 / generator / util / JavaIdentifierNormalizer.java
index c98a03dfc7116e8d8b4511d1c79bc3e2b11129a6..714807bd8332b7b0399138a7562436ef12c4d091 100644 (file)
@@ -10,12 +10,13 @@ package org.opendaylight.mdsal.binding.javav2.generator.util;
 import com.google.common.annotations.Beta;
 import com.google.common.base.CharMatcher;
 import com.google.common.base.Splitter;
-import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ListMultimap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.regex.Pattern;
+import org.opendaylight.mdsal.binding.javav2.generator.context.ModuleContext;
 import org.opendaylight.mdsal.binding.javav2.model.api.Enumeration;
 import org.opendaylight.mdsal.binding.javav2.model.api.Enumeration.Pair;
 import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
@@ -121,6 +122,7 @@ import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
  * </li>
  * </ul>
  *
+ * <p>
  * There is special case in CLASS, INTERFACE, ENUM, ENUM VALUE, CONSTANT, METHOD
  * and VARIABLE if identifier contains single dash - then the converter ignores
  * the single dash in the way of the non-java chars. In other way, if dash is
@@ -157,6 +159,7 @@ import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
  * </li>
  * </ul>
  *
+ * <p>
  * Next special case talks about normalizing class name which already exists in
  * package - but with different camel cases (foo, Foo, fOo, ...). To every next
  * classes with same names will by added their actual rank (serial number),
@@ -205,12 +208,9 @@ public final class JavaIdentifierNormalizer {
         "java",
         "com");
 
-    private static final int FIRST_CHAR = 0;
-    private static final int FIRST_INDEX = 1;
     private static final char UNDERSCORE = '_';
     private static final char DASH = '-';
     private static final String RESERVED_KEYWORD = "reserved_keyword";
-    private static final ListMultimap<String, String> PACKAGES_MAP = ArrayListMultimap.create();
     private static final Set<String> PRIMITIVE_TYPES = ImmutableSet.of("char[]", "byte[]");
 
     private static final CharMatcher DASH_MATCHER = CharMatcher.is(DASH);
@@ -219,6 +219,8 @@ public final class JavaIdentifierNormalizer {
     private static final Splitter DOT_SPLITTER = Splitter.on('.');
     private static final Splitter UNDERSCORE_SPLITTER = Splitter.on(UNDERSCORE);
 
+    private static final Pattern DOUBLE_UNDERSCORE_PATTERN = Pattern.compile("__", Pattern.LITERAL);
+
     // Converted to lower case
     private static final Set<String> WINDOWS_RESERVED_WORDS = BindingMapping.WINDOWS_RESERVED_WORDS.stream()
             .map(String::toLowerCase).collect(ImmutableSet.toImmutableSet());
@@ -245,6 +247,7 @@ public final class JavaIdentifierNormalizer {
      * }
      * </pre>
      *
+     * <p>
      * YANG enum values will be mapped to 'FOO' and 'FOO_1' Java enum values.
      *
      * @param name
@@ -254,7 +257,7 @@ public final class JavaIdentifierNormalizer {
      * @return converted and fixed name of new enum value
      */
     public static String normalizeEnumValueIdentifier(final String name, final List<Pair> values) {
-        return convertIdentifierEnumValue(name, name, values, FIRST_INDEX);
+        return convertIdentifierEnumValue(name, name, values, 1);
     }
 
     /**
@@ -272,11 +275,15 @@ public final class JavaIdentifierNormalizer {
 
         final StringBuilder sb = new StringBuilder(fullPackageName.length());
         while (true) {
-            sb.append(normalizePartialPackageName(it.next()));
+            String next = it.next();
+            sb.append(normalizePartialPackageName(next));
             if (!it.hasNext()) {
                 return sb.toString();
             }
-            sb.append('.');
+
+            if (!next.isEmpty()) {
+                sb.append('.');
+            }
         }
     }
 
@@ -287,7 +294,7 @@ public final class JavaIdentifierNormalizer {
      *            - part of package name
      * @return normalized name
      */
-    public static String normalizePartialPackageName(final String packageNamePart) {
+    static String normalizePartialPackageName(final String packageNamePart) {
         // if part of package name consist from java or windows reserved word, return it with
         // underscore at the end and in lower case
         final String lowerPart = packageNamePart.toLowerCase();
@@ -331,7 +338,8 @@ public final class JavaIdentifierNormalizer {
      *            - name of identifier
      * @return - java acceptable identifier
      */
-    public static String normalizeClassIdentifier(final String packageName, final String className) {
+    static String normalizeClassIdentifier(final String packageName, final String className,
+            final ModuleContext context) {
         if (packageName.isEmpty() && PRIMITIVE_TYPES.contains(className)) {
             return className;
         }
@@ -348,12 +356,45 @@ public final class JavaIdentifierNormalizer {
         if (lastDot != -1 && Character.isUpperCase(packageName.charAt(lastDot + 1))) {
             // ignore class name in package name - inner class name has to be normalized according to original package
             // of parent class
-            basePackageName = packageName.substring(FIRST_CHAR, lastDot);
+            basePackageName = packageName.substring(0, lastDot);
         } else {
             basePackageName = packageName;
         }
 
-        return normalizeClassIdentifier(basePackageName, convertedClassName, convertedClassName, FIRST_INDEX);
+        return normalizeClassIdentifier(basePackageName, convertedClassName, convertedClassName, 1, context);
+    }
+
+    /**
+     * Checking while there doesn't exist any class name with the same name
+     * (regardless of camel cases) in package.
+     *
+     * @param packageName
+     *            - package of class name
+     * @param origClassName
+     *            - original class name
+     * @param actualClassName
+     *            - actual class name with rank (serial number)
+     * @param rank
+     *            - actual rank (serial number)
+     * @return converted identifier
+     */
+    private static String normalizeClassIdentifier(final String packageName, final String origClassName,
+            final String actualClassName, final int rank, final ModuleContext context) {
+
+        final ListMultimap<String, String> packagesMap = context.getPackagesMap();
+
+        synchronized (packagesMap) {
+            if (packagesMap.containsKey(packageName)) {
+                for (final String existingName : packagesMap.get(packageName)) {
+                    if (actualClassName.equalsIgnoreCase(existingName)) {
+                        return normalizeClassIdentifier(packageName, origClassName, origClassName + rank,
+                                rank + 1, context);
+                    }
+                }
+            }
+            context.putToPackagesMap(packageName, actualClassName);
+            return actualClassName;
+        }
     }
 
     /**
@@ -377,10 +418,10 @@ public final class JavaIdentifierNormalizer {
 
         // check and convert first char in identifier if there is non-java char
         final StringBuilder sb = new StringBuilder();
-        final char firstChar = identifier.charAt(FIRST_CHAR);
+        final char firstChar = identifier.charAt(0);
         if (!Character.isJavaIdentifierStart(firstChar)) {
             // converting first char of identifier
-            sb.append(convertFirst(firstChar, existNext(identifier, FIRST_CHAR)));
+            sb.append(convertFirst(firstChar, existNext(identifier, 0)));
         } else {
             sb.append(firstChar);
         }
@@ -389,7 +430,7 @@ public final class JavaIdentifierNormalizer {
             final char actualChar = identifier.charAt(i);
             // ignore single dash as non java char - if there is more dashes in a row or dash is as
             // the last char in identifier then parse these dashes as non java chars
-            if (actualChar == '-' && existNext(identifier, i)) {
+            if (actualChar == DASH && existNext(identifier, i)) {
                 if (identifier.charAt(i - 1) != DASH && identifier.charAt(i + 1) != DASH) {
                     sb.append(UNDERSCORE);
                     continue;
@@ -402,43 +443,15 @@ public final class JavaIdentifierNormalizer {
                 sb.append(actualChar);
             }
         }
-        // apply camel case in appropriate way
-        return fixCasesByJavaType(sb.toString().replace("__", "_").toLowerCase(), javaIdentifier);
-    }
-
-    /**
-     * Checking while there doesn't exist any class name with the same name
-     * (regardless of camel cases) in package.
-     *
-     * @param packageName
-     *            - package of class name
-     * @param origClassName
-     *            - original class name
-     * @param actualClassName
-     *            - actual class name with rank (serial number)
-     * @param rank
-     *            - actual rank (serial number)
-     * @return converted identifier
-     */
-    private static String normalizeClassIdentifier(final String packageName, final String origClassName,
-            final String actualClassName, final int rank) {
 
-        // FIXME: this does not look thread-safe and seems to leak memory
-        if (PACKAGES_MAP.containsKey(packageName)) {
-            for (final String existingName : PACKAGES_MAP.get(packageName)) {
-                if (actualClassName.equalsIgnoreCase(existingName)) {
-                    return normalizeClassIdentifier(packageName, origClassName, origClassName + rank, rank + 1);
-                }
-            }
-        }
-        PACKAGES_MAP.put(packageName, actualClassName);
-        return actualClassName;
+        // apply camel case in appropriate way
+        return fixCasesByJavaType(DOUBLE_UNDERSCORE_PATTERN.matcher(sb).replaceAll("_").toLowerCase(), javaIdentifier);
     }
 
     /**
-     * Fix cases of converted identifiers by Java type
+     * Fix cases of converted identifiers by Java type.
      *
-     * @param string
+     * @param convertedIdentifier
      *            - converted identifier
      * @param javaIdentifier
      *            - java type of identifier
@@ -485,7 +498,7 @@ public final class JavaIdentifierNormalizer {
     }
 
     /**
-     * Check if there exist next char in identifier behind actual char position
+     * Check if there exist next char in identifier behind actual char position.
      *
      * @param identifier
      *            - original identifier
@@ -499,24 +512,24 @@ public final class JavaIdentifierNormalizer {
 
     /**
      * Converting first char of identifier. This happen only if this char is
-     * non-java char
+     * non-java char.
      *
-     * @param c
+     * @param firstChar
      *            - first char
      * @param existNext
      *            - existing of next char behind actual char
      * @return converted char
      */
-    private static String convertFirst(final char c, final boolean existNext) {
-        final String name = DASH_OR_SPACE_MATCHER.replaceFrom(Character.getName(c), UNDERSCORE);
+    private static String convertFirst(final char firstChar, final boolean existNext) {
+        final String name = DASH_OR_SPACE_MATCHER.replaceFrom(Character.getName(firstChar), UNDERSCORE);
         return existNext ? name + '_' : name;
     }
 
     /**
      * Converting any char in java identifier, This happen only if this char is
-     * non-java char
+     * non-java char.
      *
-     * @param c
+     * @param actualChar
      *            - actual char
      * @param existNext
      *            - existing of next char behind actual char
@@ -524,18 +537,18 @@ public final class JavaIdentifierNormalizer {
      *            - last char of partial converted identifier
      * @return converted char
      */
-    private static String convert(final char c, final boolean existNext, final char partialLastChar) {
-        return partialLastChar == '_' ? convertFirst(c, existNext) : "_" + convertFirst(c, existNext);
+    private static String convert(final char actualChar, final boolean existNext, final char partialLastChar) {
+        return partialLastChar == '_' ? convertFirst(actualChar, existNext) : "_" + convertFirst(actualChar, existNext);
     }
 
     /**
-     * Capitalize input string
+     * Capitalize input string.
      *
      * @param identifier
      *            - string to be capitalized
      */
     private static String capitalize(final String identifier) {
-        return identifier.substring(FIRST_CHAR, FIRST_CHAR + 1).toUpperCase() + identifier.substring(1);
+        return identifier.substring(0, 1).toUpperCase() + identifier.substring(1);
     }
 
     private static String convertIdentifierEnumValue(final String name, final String origName, final List<Pair> values,