/ app / src / main / java / com / reandroid / common / SymbolGenerationUtils.java
SymbolGenerationUtils.java
 1  /*
 2   *  Copyright (C) 2022 github.com/REAndroid
 3   *
 4   *  Licensed under the Apache License, Version 2.0 (the "License");
 5   *  you may not use this file except in compliance with the License.
 6   *  You may obtain a copy of the License at
 7   *
 8   *      http://www.apache.org/licenses/LICENSE-2.0
 9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  // Copied and modified from AOSP
18  package com.reandroid.common;
19  
20  import com.reandroid.utils.collection.CollectionUtil;
21  
22  import java.util.Set;
23  
24  public class SymbolGenerationUtils {
25  
26      public static String generateLowercase(int index) {
27          return generate(index, false);
28      }
29      public static String generateMixedCase(int index) {
30          return generate(index, true);
31      }
32      public static String generate(int index, boolean mixedCase) {
33          int size = 1;
34          int number = index + 1;
35          int maximumNumberOfCharacters = mixedCase ? TOTAL_CHARACTERS : LOWERCASE_AND_SUFFIX;
36          int firstNumberOfCharacters = maximumNumberOfCharacters - SUFFIX_LENGTH;
37  
38          int availableCharacters;
39          for(availableCharacters = firstNumberOfCharacters; number > availableCharacters; ++size) {
40              number = (number - 1) / availableCharacters;
41              availableCharacters = maximumNumberOfCharacters;
42          }
43  
44          char[] characters = new char[size];
45          number = index + 1;
46          int i = 0;
47          availableCharacters = firstNumberOfCharacters;
48  
49          int firstLetterPadding;
50          for(firstLetterPadding = SUFFIX_LENGTH; number > availableCharacters; firstLetterPadding = 0) {
51              characters[i++] = CHARACTERS[(number - 1) % availableCharacters + firstLetterPadding];
52              number = (number - 1) / availableCharacters;
53              availableCharacters = maximumNumberOfCharacters;
54          }
55  
56          characters[i] = CHARACTERS[number - 1 + firstLetterPadding];
57  
58          String symbol = new String(characters);
59          if(isReserved(symbol)) {
60              return generate(index + 1, mixedCase);
61          }
62          return symbol;
63      }
64      private static boolean isReserved(String symbol) {
65          return symbol.length() > 1 && RESERVED_NAMES.contains(symbol);
66      }
67  
68      static {
69  
70          char[] charArray = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
71                  .toCharArray();
72  
73          CHARACTERS = charArray;
74          int length = charArray.length;
75          TOTAL_CHARACTERS = length;
76          LOWERCASE_AND_SUFFIX = length - 26;
77          SUFFIX_LENGTH = 10;
78  
79          RESERVED_NAMES = CollectionUtil.newHashSet(
80                  "boolean", "byte", "char",
81                  "double", "float", "int",
82                  "long", "short", "void", "it",
83                  "by", "class");
84      }
85  
86      private static final char[] CHARACTERS;
87      private static final int TOTAL_CHARACTERS;
88      private static final int LOWERCASE_AND_SUFFIX;
89      private static final int SUFFIX_LENGTH;
90  
91      private static final Set<String> RESERVED_NAMES;
92  }