1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.prometheus.data;
18
19 import io.github.tonywasher.joceanus.gordianknot.api.base.GordianException;
20 import io.github.tonywasher.joceanus.gordianknot.api.factory.GordianFactory;
21 import io.github.tonywasher.joceanus.gordianknot.api.keyset.GordianKeySet;
22 import io.github.tonywasher.joceanus.gordianknot.api.keyset.GordianKeySetFactory;
23 import io.github.tonywasher.joceanus.gordianknot.util.GordianUtilities;
24 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataList;
25 import io.github.tonywasher.joceanus.metis.data.MetisDataResource;
26 import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
27 import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
28 import io.github.tonywasher.joceanus.metis.field.MetisFieldVersionedSet;
29 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
30 import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
31 import io.github.tonywasher.joceanus.prometheus.data.PrometheusCryptographyData.PrometheusControlKeyCtl;
32 import io.github.tonywasher.joceanus.prometheus.data.PrometheusCryptographyData.PrometheusControlKeySetCtl;
33 import io.github.tonywasher.joceanus.prometheus.data.PrometheusCryptographyData.PrometheusDataKeySetCtl;
34 import io.github.tonywasher.joceanus.prometheus.data.PrometheusData.PrometheusDataSetCtl;
35 import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataKeySet.PrometheusDataKeySetList;
36 import io.github.tonywasher.joceanus.prometheus.exc.PrometheusDataException;
37 import io.github.tonywasher.joceanus.prometheus.exc.PrometheusSecurityException;
38
39 import java.util.ArrayList;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Objects;
43
44
45
46
47
48
49 public class PrometheusControlKeySet
50 extends PrometheusDataItem
51 implements PrometheusControlKeySetCtl {
52
53
54
55 public static final String OBJECT_NAME = PrometheusCryptographyDataType.CONTROLKEYSET.getItemName();
56
57
58
59
60 public static final String LIST_NAME = PrometheusCryptographyDataType.CONTROLKEYSET.getListName();
61
62
63
64
65 public static final int WRAPLEN = GordianUtilities.getMaximumKeySetWrapLength();
66
67
68
69
70 private static final MetisFieldVersionedSet<PrometheusControlKeySet> FIELD_DEFS = MetisFieldVersionedSet.newVersionedFieldSet(PrometheusControlKeySet.class);
71
72
73
74
75 static {
76 FIELD_DEFS.declareLinkField(PrometheusCryptographyDataType.CONTROLKEY);
77 FIELD_DEFS.declareByteArrayField(PrometheusDataResource.KEYSET_KEYSETDEF, WRAPLEN);
78 FIELD_DEFS.declareDerivedVersionedField(PrometheusDataResource.KEYSET_KEYSET);
79 FIELD_DEFS.declareLocalField(PrometheusDataResource.DATAKEYSET_LIST, PrometheusControlKeySet::getDataKeySets);
80 }
81
82
83
84
85 private DataKeySetCache theKeySetCache = new DataKeySetCache();
86
87
88
89
90
91
92
93 protected PrometheusControlKeySet(final PrometheusControlKeySetList pList,
94 final PrometheusControlKeySet pSource) {
95
96 super(pList, pSource);
97
98
99 if (Objects.requireNonNull(getStyle()) == PrometheusListStyle.CLONE) {
100 final GordianKeySet myKeySet = pSource.getKeySet();
101 setValueKeySet(myKeySet);
102 }
103 }
104
105
106
107
108
109
110
111
112 private PrometheusControlKeySet(final PrometheusControlKeySetList pList,
113 final PrometheusDataValues pValues) throws OceanusException {
114
115 super(pList, pValues);
116
117
118 final PrometheusDataSetCtl myData = getDataSet();
119
120
121 Object myValue = pValues.getValue(PrometheusCryptographyDataType.CONTROLKEY);
122 if (myValue instanceof Integer i) {
123
124 setValueControlKey(i);
125
126
127 resolveDataLink(PrometheusCryptographyDataType.CONTROLKEY, PrometheusCryptographyDataType.CONTROLKEY);
128 } else if (myValue instanceof PrometheusControlKeyCtl k) {
129
130 setValueControlKey(k);
131 }
132
133
134 final PrometheusControlKeyCtl myControl = getControlKey();
135
136
137 myValue = pValues.getValue(PrometheusDataResource.KEYSET_KEYSETDEF);
138 if (myValue instanceof byte[] ba) {
139 setValueSecuredKeySetDef(ba);
140 }
141
142
143 myValue = pValues.getValue(PrometheusDataResource.KEYSET_KEYSET);
144 if (myValue instanceof GordianKeySet ks) {
145 setValueKeySet(ks);
146 } else if (getSecuredKeySetDef() != null) {
147
148 try {
149 final GordianKeySet myKeySet = getSecurityFactory().getEmbeddedKeySet().deriveKeySet(getSecuredKeySetDef());
150 setValueKeySet(myKeySet);
151 } catch (GordianException e) {
152 throw new PrometheusSecurityException(e);
153 }
154 }
155
156
157 myControl.registerControlKeySet(this);
158 }
159
160
161
162
163
164
165
166
167 protected PrometheusControlKeySet(final PrometheusControlKeySetList pList,
168 final PrometheusControlKeyCtl pControlKey) throws OceanusException {
169
170 super(pList, 0);
171
172
173 try {
174
175 setValueControlKey(pControlKey);
176
177
178 final PrometheusDataSetCtl myData = getDataSet();
179
180
181 final GordianFactory myFactory = getSecurityFactory();
182 final GordianKeySetFactory myKeySets = myFactory.getKeySetFactory();
183 final GordianKeySet myKeySet = myKeySets.generateKeySet(getDataSet().getKeySetSpec());
184 setValueKeySet(myKeySet);
185
186
187 setValueSecuredKeySetDef(myFactory.getEmbeddedKeySet().secureKeySet(myKeySet));
188
189
190 allocateDataKeySets(myData);
191
192
193 } catch (GordianException
194 | OceanusException e) {
195
196 throw new PrometheusDataException(this, ERROR_CREATEITEM, e);
197 }
198 }
199
200 @Override
201 public MetisFieldSetDef getDataFieldSet() {
202 return FIELD_DEFS;
203 }
204
205 @Override
206 public GordianFactory getSecurityFactory() {
207 final PrometheusControlKeyCtl myControl = getControlKey();
208 return myControl == null ? null : myControl.getSecurityFactory();
209 }
210
211
212
213
214
215
216 private DataKeySetCache getDataKeySets() {
217 return theKeySetCache;
218 }
219
220
221
222
223
224
225 PrometheusDataKeySet getNextDataKeySet() {
226 return theKeySetCache.getNextDataKeySet();
227 }
228
229
230
231
232
233
234 public final PrometheusControlKeyCtl getControlKey() {
235 return getValues().getValue(PrometheusCryptographyDataType.CONTROLKEY, PrometheusControlKeyCtl.class);
236 }
237
238
239
240
241
242
243 public Integer getControlKeyId() {
244 final PrometheusControlKeyCtl myKey = getControlKey();
245 return myKey == null
246 ? null
247 : myKey.getIndexedId();
248 }
249
250
251
252
253
254
255 public final byte[] getSecuredKeySetDef() {
256 return getValues().getValue(PrometheusDataResource.KEYSET_KEYSETDEF, byte[].class);
257 }
258
259 @Override
260 public GordianKeySet getKeySet() {
261 return getValues().getValue(PrometheusDataResource.KEYSET_KEYSET, GordianKeySet.class);
262 }
263
264
265
266
267
268
269
270 private void setValueControlKey(final Integer pId) throws OceanusException {
271 getValues().setValue(PrometheusCryptographyDataType.CONTROLKEY, pId);
272 }
273
274
275
276
277
278
279
280 private void setValueControlKey(final PrometheusControlKeyCtl pKey) throws OceanusException {
281 getValues().setValue(PrometheusCryptographyDataType.CONTROLKEY, pKey);
282 }
283
284
285
286
287
288
289 private void setValueSecuredKeySetDef(final byte[] pValue) {
290 getValues().setUncheckedValue(PrometheusDataResource.KEYSET_KEYSETDEF, pValue);
291 }
292
293
294
295
296
297
298 private void setValueKeySet(final GordianKeySet pValue) {
299 getValues().setUncheckedValue(PrometheusDataResource.KEYSET_KEYSET, pValue);
300 }
301
302 @Override
303 public PrometheusControlKeySet getBase() {
304 return (PrometheusControlKeySet) super.getBase();
305 }
306
307 @Override
308 public PrometheusControlKeySetList getList() {
309 return (PrometheusControlKeySetList) super.getList();
310 }
311
312 @Override
313 public int compareValues(final PrometheusDataItem pThat) {
314
315 return 0;
316 }
317
318 @Override
319 public void resolveDataSetLinks() throws OceanusException {
320
321 final PrometheusDataSetCtl myData = getDataSet();
322 resolveDataLink(PrometheusCryptographyDataType.CONTROLKEY, PrometheusCryptographyDataType.CONTROLKEY);
323 final PrometheusControlKeyCtl myControlKey = getControlKey();
324
325
326 myControlKey.registerControlKeySet(this);
327 }
328
329
330
331
332
333
334
335 private void allocateDataKeySets(final PrometheusDataSetCtl pData) throws OceanusException {
336
337 final PrometheusDataKeySetList mySets
338 = pData.getDataList(PrometheusCryptographyDataType.DATAKEYSET, PrometheusDataKeySetList.class);
339 setNewVersion();
340
341
342 final int myNumKeySets = pData.getNumActiveKeySets();
343 for (int i = 0; i < myNumKeySets; i++) {
344
345 final PrometheusDataKeySet mySet = new PrometheusDataKeySet(mySets, this);
346 mySet.setNewVersion();
347 mySets.add(mySet);
348
349
350 theKeySetCache.registerDataKeySet(mySet);
351 }
352 }
353
354
355
356
357 protected void deleteControlKeySet() {
358
359 setDeleted(true);
360
361
362 theKeySetCache.deleteDataKeySets();
363 }
364
365 @Override
366 public void registerDataKeySet(final PrometheusDataKeySetCtl pKeySet) {
367
368 theKeySetCache.registerDataKeySet((PrometheusDataKeySet) pKeySet);
369 }
370
371
372
373
374 public static class PrometheusControlKeySetList
375 extends PrometheusDataList<PrometheusControlKeySet> {
376
377
378
379 private static final MetisFieldSet<PrometheusControlKeySetList> FIELD_DEFS = MetisFieldSet.newFieldSet(PrometheusControlKeySetList.class);
380
381
382
383
384
385
386 protected PrometheusControlKeySetList(final PrometheusDataSetCtl pData) {
387 this(pData, PrometheusListStyle.CORE);
388 }
389
390
391
392
393
394
395
396 protected PrometheusControlKeySetList(final PrometheusDataSetCtl pData,
397 final PrometheusListStyle pStyle) {
398 super(PrometheusControlKeySet.class, pData, PrometheusCryptographyDataType.CONTROLKEYSET, pStyle);
399 }
400
401
402
403
404
405
406 private PrometheusControlKeySetList(final PrometheusControlKeySetList pSource) {
407 super(pSource);
408 }
409
410 @Override
411 public MetisFieldSet<PrometheusControlKeySetList> getDataFieldSet() {
412 return FIELD_DEFS;
413 }
414
415 @Override
416 public String listName() {
417 return LIST_NAME;
418 }
419
420 @Override
421 public MetisFieldSet<PrometheusControlKeySet> getItemFields() {
422 return PrometheusControlKeySet.FIELD_DEFS;
423 }
424
425 @Override
426 public boolean includeDataXML() {
427 return false;
428 }
429
430 @Override
431 protected PrometheusControlKeySetList getEmptyList(final PrometheusListStyle pStyle) {
432 final PrometheusControlKeySetList myList = new PrometheusControlKeySetList(this);
433 myList.setStyle(pStyle);
434 return myList;
435 }
436
437 @Override
438 public PrometheusControlKeySetList deriveList(final PrometheusListStyle pStyle) throws OceanusException {
439 return (PrometheusControlKeySetList) super.deriveList(pStyle);
440 }
441
442 @Override
443 public PrometheusControlKeySetList deriveDifferences(final PrometheusDataSetCtl pDataSet,
444 final PrometheusDataList<?> pOld) {
445 return (PrometheusControlKeySetList) super.deriveDifferences(pDataSet, pOld);
446 }
447
448 @Override
449 public PrometheusControlKeySet addCopyItem(final PrometheusDataItem pItem) {
450
451 if (!(pItem instanceof PrometheusControlKeySet)) {
452 return null;
453 }
454
455
456 final PrometheusControlKeySet mySet = new PrometheusControlKeySet(this, (PrometheusControlKeySet) pItem);
457 add(mySet);
458 return mySet;
459 }
460
461 @Override
462 public PrometheusControlKeySet addNewItem() {
463 throw new UnsupportedOperationException();
464 }
465
466 @Override
467 public PrometheusControlKeySet addValuesItem(final PrometheusDataValues pValues) throws OceanusException {
468
469 final PrometheusControlKeySet mySet = new PrometheusControlKeySet(this, pValues);
470
471
472 if (!isIdUnique(mySet.getIndexedId())) {
473 mySet.addError(ERROR_DUPLICATE, MetisDataResource.DATA_ID);
474 throw new PrometheusDataException(mySet, ERROR_VALIDATION);
475 }
476
477
478 add(mySet);
479
480
481 return mySet;
482 }
483
484
485
486
487
488
489
490
491
492 protected PrometheusControlKeySet cloneControlKeySet(final PrometheusControlKeyCtl pControlKey,
493 final PrometheusControlKeySet pKeySet) throws OceanusException {
494
495 final PrometheusDataValues myValues = new PrometheusDataValues(OBJECT_NAME);
496 myValues.addValue(MetisDataResource.DATA_ID, pKeySet.getIndexedId());
497 myValues.addValue(PrometheusCryptographyDataType.CONTROLKEY, pControlKey);
498 myValues.addValue(PrometheusDataResource.KEYSET_KEYSETDEF, pKeySet.getSecuredKeySetDef());
499 myValues.addValue(PrometheusDataResource.KEYSET_KEYSET, pKeySet.getKeySet());
500
501
502 final PrometheusControlKeySet mySet = addValuesItem(myValues);
503
504
505 final PrometheusDataSetCtl myData = getDataSet();
506 final PrometheusDataKeySetList myKeySets
507 = myData.getDataList(PrometheusCryptographyDataType.DATAKEYSET, PrometheusDataKeySetList.class);
508
509
510 final DataKeySetCache mySource = pKeySet.getDataKeySets();
511 mySet.theKeySetCache = mySource.cloneDataKeySetCache(mySet, myKeySets);
512
513 return mySet;
514 }
515
516 @Override
517 public void postProcessOnLoad() throws OceanusException {
518
519 reSort();
520 }
521
522 @Override
523 protected PrometheusDataMapItem allocateDataMap() {
524
525 throw new UnsupportedOperationException();
526 }
527 }
528
529
530
531
532 private static final class DataKeySetCache
533 implements MetisFieldItem, MetisDataList<PrometheusDataKeySet> {
534
535
536
537 private static final MetisFieldSet<DataKeySetCache> FIELD_DEFS = MetisFieldSet.newFieldSet(DataKeySetCache.class);
538
539
540
541
542 static {
543 FIELD_DEFS.declareLocalField(MetisDataResource.LIST_SIZE, DataKeySetCache::size);
544 }
545
546
547
548
549 private final List<PrometheusDataKeySet> theList;
550
551
552
553
554 private Iterator<PrometheusDataKeySet> theIterator;
555
556
557
558
559 DataKeySetCache() {
560 theList = new ArrayList<>();
561 }
562
563 @Override
564 public MetisFieldSet<DataKeySetCache> getDataFieldSet() {
565 return FIELD_DEFS;
566 }
567
568 @Override
569 public List<PrometheusDataKeySet> getUnderlyingList() {
570 return theList;
571 }
572
573 @Override
574 public String formatObject(final OceanusDataFormatter pFormatter) {
575 return getDataFieldSet().getName();
576 }
577
578
579
580
581
582
583 private void registerDataKeySet(final PrometheusDataKeySet pKeySet) {
584
585 if (!theList.contains(pKeySet)) {
586
587 theList.add(pKeySet);
588
589
590 if (theIterator != null) {
591 theIterator = iterator();
592 }
593 }
594 }
595
596
597
598
599
600
601 private PrometheusDataKeySet getNextDataKeySet() {
602
603 if (isEmpty()) {
604 return null;
605 }
606
607
608 if (theIterator == null
609 || !theIterator.hasNext()) {
610 theIterator = iterator();
611 }
612
613
614 return theIterator.next();
615 }
616
617
618
619
620 private void deleteDataKeySets() {
621
622 final Iterator<PrometheusDataKeySet> myIterator = iterator();
623 while (myIterator.hasNext()) {
624 final PrometheusDataKeySet mySet = myIterator.next();
625
626
627 mySet.deleteDataKeySet();
628 }
629 }
630
631
632
633
634
635
636
637
638
639 private DataKeySetCache cloneDataKeySetCache(final PrometheusControlKeySet pControlKeySet,
640 final PrometheusDataKeySetList pKeySets) throws OceanusException {
641
642 final DataKeySetCache myCache = new DataKeySetCache();
643
644
645 final Iterator<PrometheusDataKeySet> myIterator = iterator();
646 while (myIterator.hasNext()) {
647 final PrometheusDataKeySet mySet = myIterator.next();
648
649
650 final PrometheusDataKeySet myNewSet = pKeySets.cloneDataKeySet(pControlKeySet, mySet);
651 myCache.registerDataKeySet(myNewSet);
652 }
653
654
655 return myCache;
656 }
657 }
658 }