Skip to content

Commit 9627873

Browse files
committed
fix(metaDataProduction): add class simple name as a tie-breaker when sorting producers - should make a more stable production of instance meta data (specifically, can make the JoinGraph more stable).
This is a potentially breaking change, in case anyone relied on the previous sort tie breaker (which was not specified by this class). To get the previous behavior, the system property qqq.MetaDataProducerHelper.disableNameTiebreaker can be set to true.
1 parent 24cb18c commit 9627873

File tree

1 file changed

+40
-7
lines changed

1 file changed

+40
-7
lines changed

qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,16 @@
5757

5858

5959
/*******************************************************************************
60-
** Help work with MetaDataProducers.
60+
* Help work with MetaDataProducers.
61+
*
62+
* <p>Note that all of the public methods here use {@code sortMetaDataProducers},
63+
* which by default will sort by the sortOrder specified in the producer objects,
64+
* then by the type that they return, and finally by their class simple name.
65+
* But - this sorting by class simple name was added in 0.40.0. Prior to that,
66+
* there was no tie breaker on the sort. To restore the previous behavior, set
67+
* the system property {@code qqq.MetaDataProducerHelper.disableNameTiebreaker}
68+
* to {@code true}.</p>
69+
*
6170
*******************************************************************************/
6271
public class MetaDataProducerHelper
6372
{
@@ -69,7 +78,7 @@ public class MetaDataProducerHelper
6978
static
7079
{
7180
////////////////////////////////////////////////////////////////////////////////////////
72-
// define how we break ties in sort-order based on the meta-dta type. e.g., do apps //
81+
// define how we break ties in sort-order based on the meta-data type. e.g., do apps //
7382
// after all other types (as apps often try to get other types from the instance) //
7483
// also - do backends earlier than others (e.g., tables may expect backends to exist) //
7584
// any types not in the map get the default value. //
@@ -111,6 +120,7 @@ public static void processAllMetaDataProducersInPackage(QInstance instance, Stri
111120
}
112121

113122

123+
114124
/***************************************************************************
115125
**
116126
***************************************************************************/
@@ -190,11 +200,15 @@ public static List<MetaDataProducerInterface<?>> findProducers(String packageNam
190200

191201

192202
/***************************************************************************
193-
**
203+
* sort a list of producers: First by the sortOrder specified in the producer objects.
204+
* Second based on their types, so kinds that depend on other kinds come later.
205+
* Third, by class simple name, to give stable ordering (unless opt'ed out by system property).
206+
* Note, we use simple name instead of name, in case, for some reason, you wanted to control
207+
* the sort by naming your classes a certain way - easier to change Simple names than packages.
194208
***************************************************************************/
195209
public static void sortMetaDataProducers(List<MetaDataProducerInterface<?>> producers)
196210
{
197-
producers.sort(Comparator
211+
Comparator<MetaDataProducerInterface<?>> comparator = Comparator
198212
.comparing((MetaDataProducerInterface<?> p) -> p.getSortOrder())
199213
.thenComparing((MetaDataProducerInterface<?> p) ->
200214
{
@@ -207,7 +221,26 @@ public static void sortMetaDataProducers(List<MetaDataProducerInterface<?>> prod
207221
{
208222
return (0);
209223
}
210-
}));
224+
});
225+
226+
//////////////////////////////////////////////////////////////////////////
227+
// read this system property each time this method is called. //
228+
// normally we might read it once into a static var - but, e.g., tests //
229+
// might need to change the value over time. and this isn't a hot code //
230+
// path at all, so we can bear the cost each time we're called in here. //
231+
//////////////////////////////////////////////////////////////////////////
232+
String propertyName = "qqq.MetaDataProducerHelper.disableNameTiebreaker";
233+
boolean disableNameTiebreaker = Boolean.getBoolean(propertyName);
234+
if(disableNameTiebreaker)
235+
{
236+
LOG.warn("Name tiebreaker is disabled for MetaDataProducerHelper.sortMetaDataProducers. This is legacy behavior, activated by system property [" + propertyName + "], which may be removed in a future release.");
237+
}
238+
else
239+
{
240+
comparator = comparator.thenComparing(p -> p.getClass().getSimpleName());
241+
}
242+
243+
producers.sort(comparator);
211244
}
212245

213246

@@ -387,8 +420,8 @@ private static MetaDataProducerInterface<?> processChildRecordListWidget(Class<?
387420
String parentTableName = getTableNameStaticFieldValue(sourceClass);
388421
String childTableName = getTableNameStaticFieldValue(childEntityClass);
389422

390-
ChildRecordListWidget childRecordListWidget = childTable.childRecordListWidget();
391-
ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer producer = new ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer(childTableName, parentTableName, childRecordListWidget);
423+
ChildRecordListWidget childRecordListWidget = childTable.childRecordListWidget();
424+
ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer producer = new ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer(childTableName, parentTableName, childRecordListWidget);
392425
producer.setSourceClass(sourceClass);
393426
return producer;
394427
}

0 commit comments

Comments
 (0)