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