1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.themis.solver.proj;
18
19 import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
20 import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
21 import io.github.tonywasher.joceanus.themis.parser.base.ThemisDataResource;
22 import io.github.tonywasher.joceanus.themis.parser.base.ThemisInstance.ThemisClassInstance;
23 import io.github.tonywasher.joceanus.themis.parser.project.ThemisFile;
24 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverDef.ThemisSolverFileDef;
25 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverDef.ThemisSolverPackageDef;
26
27 import java.util.ArrayList;
28 import java.util.List;
29
30
31
32
33 public class ThemisSolverFile
34 implements ThemisSolverFileDef, Comparable<ThemisSolverFile> {
35
36
37
38 private static final MetisFieldSet<ThemisSolverFile> FIELD_DEFS = MetisFieldSet.newFieldSet(ThemisSolverFile.class);
39
40
41
42
43 static {
44 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_CLASSES, ThemisSolverFile::getClasses);
45 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_UNDERLYING, ThemisSolverFile::getUnderlyingFile);
46 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_REFERENCED, ThemisSolverFile::getReferenced);
47 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_LOCALREFS, ThemisSolverFile::getLocalReferences);
48 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_IMPLIEDREFS, ThemisSolverFile::getImpliedReferences);
49 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_CIRCULAR, ThemisSolverFile::isCircular);
50 }
51
52
53
54
55 private final ThemisSolverPackageDef thePackage;
56
57
58
59
60 private final ThemisFile theFile;
61
62
63
64
65 private final ThemisSolverClass theTopLevel;
66
67
68
69
70 private final List<ThemisSolverClass> theClasses;
71
72
73
74
75 private final List<ThemisSolverClass> theReferenced;
76
77
78
79
80 private final List<ThemisSolverClass> theLocalReferences;
81
82
83
84
85 private final List<ThemisSolverClass> theImpliedReferences;
86
87
88
89
90 private boolean needsPreProcess;
91
92
93
94
95 private boolean isCircular;
96
97
98
99
100
101
102
103 ThemisSolverFile(final ThemisSolverPackageDef pPackage,
104 final ThemisFile pFile) {
105
106 thePackage = pPackage;
107 theFile = pFile;
108
109
110 needsPreProcess = true;
111
112
113 theClasses = new ArrayList<>();
114 for (ThemisClassInstance myClass : theFile.getClasses()) {
115 final ThemisSolverClass mySolverClass = new ThemisSolverClass(this, myClass);
116 theClasses.add(mySolverClass);
117 }
118
119
120 theTopLevel = theClasses.stream().filter(ThemisSolverClass::isTopLevel).findFirst().orElse(null);
121
122
123 theReferenced = new ArrayList<>();
124 theLocalReferences = new ArrayList<>();
125 theImpliedReferences = new ArrayList<>();
126 }
127
128 @Override
129 public MetisFieldSet<ThemisSolverFile> getDataFieldSet() {
130 return FIELD_DEFS;
131 }
132
133 @Override
134 public String formatObject(final OceanusDataFormatter pFormatter) {
135 return toString();
136 }
137
138 @Override
139 public ThemisSolverPackageDef getOwningPackage() {
140 return thePackage;
141 }
142
143 @Override
144 public ThemisFile getUnderlyingFile() {
145 return theFile;
146 }
147
148
149
150
151
152
153 public ThemisSolverClass getTopLevel() {
154 return theTopLevel;
155 }
156
157
158
159
160
161
162 public List<ThemisSolverClass> getClasses() {
163 return theClasses;
164 }
165
166
167
168
169
170
171 public List<ThemisSolverClass> getReferenced() {
172 return theReferenced;
173 }
174
175
176
177
178
179
180 public List<ThemisSolverClass> getLocalReferences() {
181 return theLocalReferences;
182 }
183
184
185
186
187
188
189 public List<ThemisSolverClass> getImpliedReferences() {
190 return theImpliedReferences;
191 }
192
193
194
195
196 public void markPreProcessed() {
197 needsPreProcess = false;
198 }
199
200
201
202
203
204
205 public boolean needsPreProcess() {
206 return needsPreProcess;
207 }
208
209
210
211
212
213
214 public boolean isCircular() {
215 return isCircular;
216 }
217
218
219
220
221
222
223 public String getLocation() {
224 return theFile.getLocation();
225 }
226
227 @Override
228 public String toString() {
229 return theFile.toString();
230 }
231
232
233
234
235
236
237 public void setReferenced(final List<ThemisSolverClass> pReferenced) {
238
239 theReferenced.addAll(pReferenced.stream().filter(s -> !s.equals(getTopLevel())).toList());
240
241
242 final String myPackage = theTopLevel.getPackageName();
243 for (ThemisSolverClass myClass : theReferenced) {
244
245 if (myClass.getPackageName().equals(myPackage)) {
246 theLocalReferences.add(myClass);
247 }
248 }
249 }
250
251
252
253
254 public void processLocalReferences() {
255
256 for (ThemisSolverClass myClass : theLocalReferences) {
257
258 processLocalReferences(myClass);
259 }
260
261
262 isCircular = theImpliedReferences.contains(theTopLevel);
263 }
264
265
266
267
268
269
270 private void processLocalReferences(final ThemisSolverClass pClass) {
271
272 if (!theImpliedReferences.contains(pClass)) {
273
274 theImpliedReferences.add(pClass);
275
276
277 if (!pClass.equals(theTopLevel)) {
278
279 for (ThemisSolverClass myClass : ((ThemisSolverFile) pClass.getOwningFile()).getLocalReferences()) {
280
281 processLocalReferences(myClass);
282 }
283 }
284 }
285 }
286
287 @Override
288 public boolean equals(final Object pThat) {
289
290 if (this == pThat) {
291 return true;
292 }
293 if (pThat == null) {
294 return false;
295 }
296
297
298 if (!(pThat instanceof ThemisSolverFile myThat)) {
299 return false;
300 }
301
302
303 return getLocation().equals(myThat.getLocation());
304 }
305
306 @Override
307 public int hashCode() {
308 return theFile.getLocation().hashCode();
309 }
310
311 @Override
312 public int compareTo(final ThemisSolverFile pThat) {
313
314 final ThemisSolverClass myClass = pThat.getTopLevel();
315
316
317 if (theImpliedReferences.contains(myClass)
318 && !pThat.getImpliedReferences().contains(theTopLevel)) {
319 return -1;
320 }
321 if (pThat.getImpliedReferences().contains(theTopLevel)
322 && !theImpliedReferences.contains(myClass)) {
323 return 1;
324 }
325
326
327 final int iDiff = pThat.theImpliedReferences.size()
328 - theImpliedReferences.size();
329 if (iDiff != 0) {
330 return iDiff;
331 }
332
333
334 return getLocation().compareTo(pThat.getLocation());
335 }
336 }