1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.generator.api.dom.kotlin;
17
18 import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;
19 import static org.mybatis.generator.internal.util.messages.Messages.getString;
20
21 import java.util.ArrayList;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Objects;
25 import java.util.Set;
26 import java.util.StringTokenizer;
27 import java.util.function.Function;
28 import java.util.stream.Collectors;
29 import java.util.stream.Stream;
30
31 public class FullyQualifiedKotlinType {
32
33 private static final Set<String> AUTOMATIC_KOTLIN_PACKAGES = new HashSet<>();
34
35 static {
36 AUTOMATIC_KOTLIN_PACKAGES.add("kotlin");
37 AUTOMATIC_KOTLIN_PACKAGES.add("kotlin.collections");
38 }
39
40 private String packageName;
41 private final List<FullyQualifiedKotlinType> typeArguments = new ArrayList<>();
42 private String shortNameWithoutTypeArguments;
43 private boolean isExplicitlyImported;
44
45 public FullyQualifiedKotlinType(String fullTypeSpecification) {
46 parse(Objects.requireNonNull(fullTypeSpecification).trim());
47 }
48
49 public String getPackageName() {
50 return packageName;
51 }
52
53 public String getShortNameWithoutTypeArguments() {
54 return shortNameWithoutTypeArguments;
55 }
56
57 public String getShortNameWithTypeArguments() {
58 if (typeArguments.isEmpty()) {
59 return shortNameWithoutTypeArguments;
60 }
61
62 return typeArguments.stream().map(FullyQualifiedKotlinType::getShortNameWithTypeArguments)
63 .collect(Collectors.joining(", ", shortNameWithoutTypeArguments
64 + "<", ">"));
65 }
66
67 public List<FullyQualifiedKotlinType> getTypeArguments() {
68 return typeArguments;
69 }
70
71 public void addTypeArgument(FullyQualifiedKotlinType typeArgument) {
72 typeArguments.add(typeArgument);
73 }
74
75
76
77
78
79
80
81 public Set<String> getImportList() {
82 Stream<String> thisImport;
83 if (isExplicitlyImported) {
84 thisImport = Stream.of(packageName + "." + shortNameWithoutTypeArguments);
85 } else {
86 thisImport = Stream.empty();
87 }
88
89 Stream<String> ss = typeArguments.stream()
90 .map(FullyQualifiedKotlinType::getImportList)
91 .flatMap(Set::stream);
92
93 return Stream.of(thisImport, ss)
94 .flatMap(Function.identity())
95 .collect(Collectors.toSet());
96 }
97
98 private void parse(String fullTypeSpecification) {
99 int index = fullTypeSpecification.indexOf('<');
100 if (index == -1) {
101 simpleParse(fullTypeSpecification);
102 } else {
103 simpleParse(fullTypeSpecification.substring(0, index));
104 int endIndex = fullTypeSpecification.lastIndexOf('>');
105 if (endIndex == -1) {
106 throw new RuntimeException(getString("RuntimeError.22", fullTypeSpecification));
107 }
108 genericParse(fullTypeSpecification.substring(index, endIndex + 1));
109 }
110 }
111
112 private void simpleParse(String typeSpecification) {
113 String baseQualifiedName = typeSpecification.trim();
114 if (baseQualifiedName.contains(".")) {
115 packageName = getPackage(baseQualifiedName);
116 shortNameWithoutTypeArguments = baseQualifiedName.substring(packageName.length() + 1);
117 isExplicitlyImported = !AUTOMATIC_KOTLIN_PACKAGES.contains(packageName);
118 } else {
119 shortNameWithoutTypeArguments = baseQualifiedName;
120 isExplicitlyImported = false;
121 packageName = "";
122 }
123 }
124
125 private void genericParse(String genericSpecification) {
126 int lastIndex = genericSpecification.lastIndexOf('>');
127 if (lastIndex == -1) {
128
129 throw new RuntimeException(getString("RuntimeError.22", genericSpecification));
130 }
131 String argumentString = genericSpecification.substring(1, lastIndex);
132
133 StringTokenizer st = new StringTokenizer(argumentString, ",<>", true);
134 int openCount = 0;
135 StringBuilder sb = new StringBuilder();
136 while (st.hasMoreTokens()) {
137 String token = st.nextToken();
138 if ("<".equals(token)) {
139 sb.append(token);
140 openCount++;
141 } else if (">".equals(token)) {
142 sb.append(token);
143 openCount--;
144 } else if (",".equals(token)) {
145 if (openCount == 0) {
146 typeArguments.add(new FullyQualifiedKotlinType(sb.toString()));
147 sb.setLength(0);
148 } else {
149 sb.append(token);
150 }
151 } else {
152 sb.append(token);
153 }
154 }
155
156 if (openCount != 0) {
157 throw new RuntimeException(getString("RuntimeError.22", genericSpecification));
158 }
159
160 String finalType = sb.toString();
161 if (stringHasValue(finalType)) {
162 typeArguments.add(new FullyQualifiedKotlinType(finalType));
163 }
164 }
165
166
167
168
169
170
171
172
173
174
175
176
177 private static String getPackage(String baseQualifiedName) {
178 int index = baseQualifiedName.lastIndexOf('.');
179 return baseQualifiedName.substring(0, index);
180 }
181 }