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.ThemisChar;
22 import io.github.tonywasher.joceanus.themis.parser.base.ThemisDataResource;
23 import io.github.tonywasher.joceanus.themis.parser.project.ThemisFile;
24 import io.github.tonywasher.joceanus.themis.parser.project.ThemisPackage;
25 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverDef.ThemisSolverModuleDef;
26 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverDef.ThemisSolverPackageDef;
27 import io.github.tonywasher.joceanus.themis.solver.proj.ThemisSolverReference.ThemisRefType;
28
29 import java.util.ArrayList;
30 import java.util.List;
31
32
33
34
35 public class ThemisSolverPackage
36 implements ThemisSolverPackageDef, Comparable<ThemisSolverPackage> {
37
38
39
40 private static final MetisFieldSet<ThemisSolverPackage> FIELD_DEFS = MetisFieldSet.newFieldSet(ThemisSolverPackage.class);
41
42
43
44
45 static {
46 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_MODULE, ThemisSolverPackage::getOwningModule);
47 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_PARENT, ThemisSolverPackage::getParent);
48 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_CHILDREN, ThemisSolverPackage::getChildren);
49 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_FILES, ThemisSolverPackage::getFiles);
50 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_UNDERLYING, ThemisSolverPackage::getUnderlyingPackage);
51 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_REFERENCED, ThemisSolverPackage::getReferenceMap);
52 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_LOCALREFS, ThemisSolverPackage::getLocalReferences);
53 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_IMPLIEDREFS, ThemisSolverPackage::getImpliedReferences);
54 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_STANDARD, ThemisSolverPackage::isStandard);
55 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_CIRCULAR, ThemisSolverPackage::isCircular);
56 FIELD_DEFS.declareLocalField(ThemisDataResource.DATA_INCESTUOUS, ThemisSolverPackage::isIncestuous);
57 }
58
59
60
61
62 private final ThemisSolverModuleDef theModule;
63
64
65
66
67 private final ThemisPackage thePackage;
68
69
70
71
72 private final String theShortName;
73
74
75
76
77 private final List<ThemisSolverFile> theFiles;
78
79
80
81
82 private final List<ThemisSolverPackage> theChildren;
83
84
85
86
87 private final ThemisSolverReference theReferenceMap;
88
89
90
91
92 private final List<ThemisSolverPackageDef> theLocalReferences;
93
94
95
96
97 private final List<ThemisSolverPackageDef> theImpliedReferences;
98
99
100
101
102 private final boolean isStandard;
103
104
105
106
107 private ThemisSolverPackage theParent;
108
109
110
111
112 private boolean isCircular;
113
114
115
116
117 private boolean isIncestuous;
118
119
120
121
122
123
124
125 ThemisSolverPackage(final ThemisSolverModuleDef pModule,
126 final ThemisPackage pPackage) {
127
128 theModule = pModule;
129 thePackage = pPackage;
130 isStandard = pPackage.isStandard();
131
132
133 final String myName = getPackageName();
134 final int iIndex = myName.lastIndexOf(ThemisChar.PERIOD);
135 theShortName = iIndex == -1 ? myName : myName.substring(iIndex + 1);
136
137
138 theReferenceMap = new ThemisSolverReference();
139 theLocalReferences = new ArrayList<>();
140 theImpliedReferences = new ArrayList<>();
141
142
143 theFiles = new ArrayList<>();
144 theChildren = new ArrayList<>();
145 for (ThemisFile myFile : thePackage.getFiles()) {
146 final ThemisSolverFile mySolverFile = new ThemisSolverFile(this, myFile);
147 theFiles.add(mySolverFile);
148 }
149 }
150
151 @Override
152 public MetisFieldSet<ThemisSolverPackage> getDataFieldSet() {
153 return FIELD_DEFS;
154 }
155
156 @Override
157 public String formatObject(final OceanusDataFormatter pFormatter) {
158 return toString();
159 }
160
161 @Override
162 public ThemisSolverModuleDef getOwningModule() {
163 return theModule;
164 }
165
166 @Override
167 public ThemisPackage getUnderlyingPackage() {
168 return thePackage;
169 }
170
171 @Override
172 public String getPackageName() {
173 return thePackage.getPackage();
174 }
175
176
177
178
179
180
181 public String getShortName() {
182 return theShortName;
183 }
184
185
186
187
188
189
190 public List<ThemisSolverFile> getFiles() {
191 return theFiles;
192 }
193
194
195
196
197
198
199 public List<ThemisSolverPackage> getChildren() {
200 return theChildren;
201 }
202
203
204
205
206
207
208 public ThemisSolverReference getReferenceMap() {
209 return theReferenceMap;
210 }
211
212 @Override
213 public List<ThemisSolverPackageDef> getLocalReferences() {
214 return theLocalReferences;
215 }
216
217
218
219
220
221
222 public List<ThemisSolverPackageDef> getImpliedReferences() {
223 return theImpliedReferences;
224 }
225
226
227
228
229
230
231 public void addChild(final ThemisSolverPackage pChild) {
232 theChildren.add(pChild);
233 pChild.setParent(this);
234 }
235
236
237
238
239
240
241 private void setParent(final ThemisSolverPackage pParent) {
242 theParent = pParent;
243 }
244
245
246
247
248
249
250 public ThemisSolverPackage getParent() {
251 return theParent;
252 }
253
254 @Override
255 public boolean isStandard() {
256 return isStandard;
257 }
258
259
260
261
262
263
264 public boolean isCircular() {
265 return isCircular;
266 }
267
268
269
270
271 public void markIncestuous() {
272 isIncestuous = true;
273 }
274
275
276
277
278
279
280 public boolean isIncestuous() {
281 return isIncestuous;
282 }
283
284
285
286
287
288
289 public boolean isPlaceHolder() {
290 return thePackage.isPlaceHolder();
291 }
292
293
294
295
296
297
298 public boolean areFilesCircular() {
299
300 for (ThemisSolverFile myFile : theFiles) {
301
302 if (myFile.isCircular()) {
303 return true;
304 }
305 }
306
307
308 return false;
309 }
310
311
312
313
314
315
316 private boolean areChildrenInError() {
317
318 for (ThemisSolverPackage myChild : theChildren) {
319
320 if (myChild.isInError()) {
321 return true;
322 }
323 }
324
325
326 return false;
327 }
328
329
330
331
332
333
334 public boolean isInError() {
335 return isCircular() || isIncestuous()
336 || areChildrenInError() || areFilesCircular();
337 }
338
339
340
341
342
343
344 public boolean isLocalInError() {
345 return isIncestuous() || areFilesCircular();
346 }
347
348
349
350
351
352
353 public boolean lackingChildReferences() {
354 return theReferenceMap.lackingReferences(ThemisRefType.CHILD);
355 }
356
357
358
359
360
361
362 public void setReferenced(final List<ThemisSolverPackageDef> pReferenced) {
363
364 theLocalReferences.addAll(pReferenced.stream().filter(s -> !s.equals(this)).toList());
365 }
366
367
368
369
370 public void processLocalReferences() {
371
372 for (ThemisSolverPackageDef myPackage : theLocalReferences) {
373
374 processLocalReferences(myPackage);
375 }
376
377
378 isCircular = theImpliedReferences.contains(this);
379 }
380
381
382
383
384
385
386 private void processLocalReferences(final ThemisSolverPackageDef pPackage) {
387
388 if (!theImpliedReferences.contains(pPackage)) {
389
390 theImpliedReferences.add(pPackage);
391
392
393 if (!pPackage.equals(this)) {
394
395 for (ThemisSolverPackageDef myPackage : pPackage.getLocalReferences()) {
396
397 processLocalReferences(myPackage);
398 }
399 }
400 }
401 }
402
403 @Override
404 public boolean equals(final Object pThat) {
405
406 if (this == pThat) {
407 return true;
408 }
409 if (pThat == null) {
410 return false;
411 }
412
413
414 if (!(pThat instanceof ThemisSolverPackage myThat)) {
415 return false;
416 }
417
418
419 return getPackageName().equals(myThat.getPackageName());
420 }
421
422 @Override
423 public int hashCode() {
424 return getPackageName().hashCode();
425 }
426
427 @Override
428 public String toString() {
429 return thePackage.toString();
430 }
431
432 @Override
433 public int compareTo(final ThemisSolverPackage pThat) {
434
435 if (theImpliedReferences.contains(pThat)
436 && !pThat.getImpliedReferences().contains(this)) {
437 return -1;
438 }
439 if (pThat.getImpliedReferences().contains(this)
440 && !theImpliedReferences.contains(pThat)) {
441 return 1;
442 }
443
444
445 final int iDiff = pThat.theImpliedReferences.size()
446 - theImpliedReferences.size();
447 if (iDiff != 0) {
448 return iDiff;
449 }
450
451
452 return getPackageName().compareTo(pThat.getPackageName());
453 }
454 }