1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package io.github.tonywasher.joceanus.themis.solver.mapper;
19
20 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
21 import io.github.tonywasher.joceanus.themis.parser.base.ThemisChar;
22 import io.github.tonywasher.joceanus.themis.parser.base.ThemisInstance.ThemisClassInstance;
23 import io.github.tonywasher.joceanus.themis.parser.base.ThemisInstance.ThemisNodeInstance;
24 import io.github.tonywasher.joceanus.themis.parser.node.ThemisNodeImport;
25 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverClass;
26 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverFile;
27 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverModule;
28 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverPackage;
29 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverProject;
30 import io.github.tonywasher.joceanus.themis.solver.reflect.ThemisReflectExternal;
31 import io.github.tonywasher.joceanus.themis.solver.reflect.ThemisReflectJar;
32
33 import java.util.ArrayList;
34 import java.util.LinkedHashMap;
35 import java.util.List;
36 import java.util.Map;
37
38
39
40
41 public class ThemisMapperProjectState
42 implements AutoCloseable {
43
44
45
46 private final Map<String, ThemisSolverClass> theProjectClasses;
47
48
49
50
51 private final Map<String, ThemisReflectExternal> theExternalClasses;
52
53
54
55
56 private final ThemisReflectJar theJar;
57
58
59
60
61
62
63
64 ThemisMapperProjectState(final ThemisSolverProject pProject) throws OceanusException {
65
66 theProjectClasses = new LinkedHashMap<>();
67 buildProjectClassMap(pProject);
68
69
70 theExternalClasses = new LinkedHashMap<>();
71 buildExternalClassMap(pProject);
72
73
74 theJar = new ThemisReflectJar(pProject.getProjectParser(), theExternalClasses);
75 theJar.processExternalClasses();
76 }
77
78
79
80
81
82
83 Map<String, ThemisSolverClass> getProjectClassMap() {
84 return theProjectClasses;
85 }
86
87
88
89
90
91
92 Map<String, ThemisReflectExternal> getExternalClassMap() {
93 return theExternalClasses;
94 }
95
96
97
98
99
100
101 private void buildProjectClassMap(final ThemisSolverProject pProject) {
102
103 for (ThemisSolverModule myModule : pProject.getModules()) {
104
105 for (ThemisSolverPackage myPackage : myModule.getPackages().values()) {
106 buildProjectClassMap(myPackage);
107 }
108 }
109 }
110
111
112
113
114
115
116 private void buildProjectClassMap(final ThemisSolverPackage pPackage) {
117
118 for (ThemisSolverFile myFile : pPackage.getFiles()) {
119
120 for (ThemisSolverClass myClass : myFile.getClasses()) {
121 theProjectClasses.put(myClass.getFullName(), myClass);
122 }
123 }
124 }
125
126
127
128
129
130
131 private void buildExternalClassMap(final ThemisSolverProject pProject) {
132
133 for (ThemisSolverModule myModule : pProject.getModules()) {
134
135 for (ThemisSolverPackage myPackage : myModule.getPackages().values()) {
136 buildExternalClassMap(myPackage);
137 }
138 }
139 }
140
141
142
143
144
145
146 private void buildExternalClassMap(final ThemisSolverPackage pPackage) {
147
148 for (ThemisSolverFile myFile : pPackage.getFiles()) {
149
150 for (ThemisNodeInstance myInstance : myFile.getUnderlyingFile().getContents().getImports()) {
151
152 final ThemisNodeImport myImport = (ThemisNodeImport) myInstance;
153 final String myFullName = myImport.getFullName();
154
155
156 if (!theProjectClasses.containsKey(myFullName)) {
157
158 theExternalClasses.computeIfAbsent(myFullName, n -> new ThemisReflectExternal(myImport));
159 }
160 }
161 }
162 }
163
164
165
166
167
168
169
170 public List<ThemisClassInstance> listAllInherited(final String pClass) {
171
172 final List<String> myAncestors = listAllAncestors(pClass);
173
174
175 final List<ThemisClassInstance> myResult = new ArrayList<>();
176 for (String myAncestor : myAncestors) {
177 listAllInherited(myResult, myAncestor);
178 }
179 return myResult;
180 }
181
182
183
184
185
186
187
188 private void listAllInherited(final List<ThemisClassInstance> pResult,
189 final String pClass) {
190 final ThemisSolverClass myProjectClass = theProjectClasses.get(pClass);
191 if (myProjectClass != null) {
192 listAllProjectInherited(pResult, myProjectClass);
193 } else {
194 listAllExternalInherited(pResult, theExternalClasses.get(pClass));
195 }
196 }
197
198
199
200
201
202
203
204 private void listAllProjectInherited(final List<ThemisClassInstance> pResult,
205 final ThemisSolverClass pClass) {
206 final String myParent = pClass.getFullName();
207 for (ThemisSolverClass myChild : theProjectClasses.values()) {
208 final String myCheckName = myParent + ThemisChar.PERIOD + myChild.getName();
209 if (myCheckName.equals(myChild.getFullName())) {
210 pResult.add(myChild.getUnderlyingClass());
211 }
212 }
213 }
214
215
216
217
218
219
220
221 private void listAllExternalInherited(final List<ThemisClassInstance> pResult,
222 final ThemisReflectExternal pClass) {
223 final String myParent = pClass.getFullName();
224 for (ThemisReflectExternal myChild : theExternalClasses.values()) {
225 final String myCheckName = myParent + ThemisChar.PERIOD + myChild.getName();
226 if (myCheckName.equals(myChild.getFullName())) {
227 pResult.add(myChild.getClassInstance());
228 }
229 }
230 }
231
232
233
234
235
236
237
238 private List<String> listAllAncestors(final String pClass) {
239 final List<String> myResult = new ArrayList<>();
240 final ThemisSolverClass myClass = theProjectClasses.get(pClass);
241 if (myClass != null) {
242 listAllProjectAncestors(myResult, myClass);
243 } else {
244 listAllExternalAncestors(myResult, theExternalClasses.get(pClass));
245 }
246 return myResult;
247 }
248
249
250
251
252
253
254
255 private void listAllProjectAncestors(final List<String> pExisting,
256 final ThemisSolverClass pClass) {
257 for (String myAncestor : pClass.getAncestors()) {
258
259 if (!pExisting.contains(myAncestor)) {
260
261 pExisting.add(myAncestor);
262
263
264 final ThemisSolverClass myClass = theProjectClasses.get(myAncestor);
265 if (myClass != null) {
266
267 listAllProjectAncestors(pExisting, myClass);
268
269
270 } else {
271 listAllExternalAncestors(pExisting, theExternalClasses.get(myAncestor));
272 }
273 }
274 }
275 }
276
277
278
279
280
281
282
283 private void listAllExternalAncestors(final List<String> pExisting,
284 final ThemisReflectExternal pClass) {
285 for (String myAncestor : pClass.getAncestors()) {
286
287 if (!pExisting.contains(myAncestor)) {
288
289 pExisting.add(myAncestor);
290 listAllExternalAncestors(pExisting, theExternalClasses.get(myAncestor));
291 }
292 }
293 }
294
295
296
297
298
299
300
301 public ThemisReflectExternal tryJavaLang(final String pName) {
302 return theJar.tryJavaLang(pName);
303 }
304
305
306
307
308
309
310
311 public ThemisReflectExternal tryNamedClass(final String pName) {
312 return theJar.tryNamedClass(pName);
313 }
314
315 @Override
316 public void close() {
317 theJar.close();
318 }
319 }