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.themis.parser.base.ThemisChar;
21 import io.github.tonywasher.joceanus.themis.parser.base.ThemisInstance.ThemisClassInstance;
22 import io.github.tonywasher.joceanus.themis.parser.base.ThemisInstance.ThemisNodeInstance;
23 import io.github.tonywasher.joceanus.themis.parser.node.ThemisNodeImport;
24 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverClass;
25 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverFile;
26 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverPackage;
27
28 import java.util.ArrayList;
29 import java.util.LinkedHashMap;
30 import java.util.List;
31 import java.util.Map;
32
33
34
35
36 public class ThemisMapperFileState {
37
38
39
40 private final ThemisMapperProjectState theProject;
41
42
43
44
45 private final Map<String, ThemisClassInstance> theKnownClasses;
46
47
48
49
50 private final List<ThemisSolverClass> theReferenced;
51
52
53
54
55
56
57 ThemisMapperFileState(final ThemisMapperProjectState pProject) {
58
59 theProject = pProject;
60
61
62 theKnownClasses = new LinkedHashMap<>();
63 theReferenced = new ArrayList<>();
64 }
65
66
67
68
69
70
71 List<ThemisSolverClass> getReferenced() {
72 return theReferenced;
73 }
74
75
76
77
78
79
80 void initForFile(final ThemisSolverFile pFile) {
81
82 theKnownClasses.clear();
83 theReferenced.clear();
84
85
86 determineKnownClasses(pFile);
87 }
88
89
90
91
92
93
94 private void determineKnownClasses(final ThemisSolverFile pFile) {
95
96 final ThemisSolverPackage myPackage = (ThemisSolverPackage) pFile.getOwningPackage();
97 for (ThemisSolverFile myFile : myPackage.getFiles()) {
98 final ThemisSolverClass myClass = myFile.getTopLevel();
99 if (myClass != null) {
100 theKnownClasses.put(myClass.getName(), myClass.getUnderlyingClass());
101 }
102 }
103
104
105 for (ThemisNodeInstance myNode : pFile.getUnderlyingFile().getContents().getImports()) {
106
107 final ThemisClassInstance myImport = lookUpImport((ThemisNodeImport) myNode);
108 theKnownClasses.put(myImport.getName(), myImport);
109 }
110
111
112 for (ThemisSolverClass myClass : pFile.getClasses()) {
113 if (!myClass.getUnderlyingClass().isAnonClass()) {
114 theKnownClasses.put(myClass.getName(), myClass.getUnderlyingClass());
115 }
116 }
117 }
118
119
120
121
122
123
124 void processInherited(final ThemisSolverClass pClass) {
125 for (ThemisClassInstance myInherited : theProject.listAllInherited(pClass.getFullName())) {
126 theKnownClasses.put(myInherited.getName(), myInherited);
127 }
128 }
129
130
131
132
133
134
135
136 private ThemisClassInstance lookUpImport(final ThemisNodeImport pImport) {
137
138 final String myFullName = pImport.getFullName();
139
140
141 final ThemisSolverClass myClass = theProject.getProjectClassMap().get(myFullName);
142 return myClass != null
143 ? myClass.getUnderlyingClass()
144 : theProject.getExternalClassMap().get(myFullName);
145 }
146
147
148
149
150
151
152
153 ThemisClassInstance processPossibleReference(final String pReference) {
154
155 ThemisClassInstance myReference = theKnownClasses.get(pReference);
156
157
158 if (myReference == null) {
159
160 final int iIndex = pReference.indexOf(ThemisChar.PERIOD);
161 if (iIndex != -1) {
162
163 myReference = lookUpFullyNamedClass(pReference);
164
165
166 if (myReference == null) {
167
168 myReference = lookUpPartiallyNamedClass(pReference, iIndex);
169 }
170
171
172 } else {
173 myReference = lookUpJavaLangClass(pReference);
174 }
175 }
176
177
178 if (myReference != null) {
179 declareReferencedClass(myReference);
180 }
181 return myReference;
182 }
183
184
185
186
187
188
189
190 private ThemisClassInstance lookUpFullyNamedClass(final String pReference) {
191
192 ThemisClassInstance myReference = theProject.getExternalClassMap().get(pReference);
193 if (myReference == null) {
194 final ThemisSolverClass myClass = theProject.getProjectClassMap().get(pReference);
195 if (myClass != null) {
196 myReference = myClass.getUnderlyingClass();
197 }
198 }
199
200
201 if (myReference == null) {
202 myReference = theProject.tryNamedClass(pReference);
203 }
204
205
206 if (myReference != null) {
207 theKnownClasses.put(pReference, myReference);
208 }
209
210
211 return myReference;
212 }
213
214
215
216
217
218
219
220
221 private ThemisClassInstance lookUpPartiallyNamedClass(final String pReference,
222 final int pIndex) {
223
224 final String myBase = pReference.substring(0, pIndex);
225 ThemisClassInstance myReference = theKnownClasses.get(myBase);
226
227
228 if (myReference != null) {
229
230 final String myName = myReference.getFullName() + pReference.substring(pIndex);
231 final ThemisSolverClass myProjectClass = theProject.getProjectClassMap().get(myName);
232 myReference = myProjectClass == null ? theProject.tryNamedClass(myName) : myProjectClass.getUnderlyingClass();
233
234
235 if (myReference != null) {
236 theKnownClasses.put(pReference, myReference);
237 }
238 }
239
240
241 return myReference;
242 }
243
244
245
246
247
248
249
250 private ThemisClassInstance lookUpJavaLangClass(final String pReference) {
251
252 final ThemisClassInstance myReference = theProject.tryJavaLang(pReference);
253
254
255 if (myReference != null) {
256 theKnownClasses.put(pReference, myReference);
257 }
258
259
260 return myReference;
261 }
262
263
264
265
266
267
268 private void declareReferencedClass(final ThemisClassInstance pClass) {
269
270 final Map<String, ThemisSolverClass> myProjectClasses = theProject.getProjectClassMap();
271 ThemisSolverClass myClass = myProjectClasses.get(pClass.getFullName());
272 if (myClass == null) {
273 return;
274 }
275
276
277 if (!myClass.isTopLevel()) {
278 myClass = ((ThemisSolverFile) myClass.getOwningFile()).getTopLevel();
279 }
280
281
282 if (myClass != null && !theReferenced.contains(myClass)) {
283
284 theReferenced.add(myClass);
285 }
286 }
287 }