Track whether Task.applicable needs to be refreshed The Properties class was previously used to track when properties end up being needed during expasion, and it was able to determine this at the granualarity of the Task and NamesFactory objects. Add the ability to track this at a finer level, specifically single at the "applicable" Field of the Task object so that a follow on change can use this to detect if the applicable field is ever going to be altered when applied to different changes in a query. If the Field is not going to ever be altered, then it becomes possible to cache other values which are based on this Field's value. Specifically, having the ability to track the refresh impact of properties on the Task.applicable Field paves the way to cache TaskTree.Node Lists based on Change Branches. Feature-Point: I4c3ff9ceb990386e0f0d11fbd55cdc825c677e4c Change-Id: Ib7d33f2bb05c318b1082311a1a05ff2f67437351
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java b/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java index 3f6870f..af8da40 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java +++ b/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
@@ -14,7 +14,7 @@ package com.googlesource.gerrit.plugins.task; -import com.google.common.collect.Sets; +import com.google.common.collect.ImmutableSet; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.server.query.change.ChangeData; import com.google.gwtorm.server.OrmException; @@ -43,6 +43,7 @@ protected Loader loader; protected boolean init = true; protected boolean isTaskRefreshNeeded; + protected boolean isApplicableRefreshRequired; protected boolean isSubNodeReloadRequired; public Properties() { @@ -61,13 +62,16 @@ loader = new Loader(changeData); expander = new Expander(n -> loader.load(n)); if (isTaskRefreshNeeded || init) { + expander.expand(task, TaskConfig.KEY_APPLICABLE); + isApplicableRefreshRequired = loader.isNonTaskDefinedPropertyLoaded(); + + expander.expand(task, ImmutableSet.of(TaskConfig.KEY_APPLICABLE, TaskConfig.KEY_NAME)); + Map<String, String> exported = expander.expand(origTask.exported); if (exported != origTask.exported) { task.getForWrite().exported = exported; } - expander.expand(task, Collections.emptySet()); - if (init) { init = false; isTaskRefreshNeeded = loader.isNonTaskDefinedPropertyLoaded(); @@ -83,6 +87,10 @@ isSubNodeReloadRequired = loader.isNonTaskDefinedPropertyLoaded(); } + public boolean isApplicableRefreshRequired() { + return isApplicableRefreshRequired; + } + public boolean isSubNodeReloadRequired() { return isSubNodeReloadRequired; } @@ -92,7 +100,7 @@ return expander.expand( namesFactory, nf -> namesFactory.config.new NamesFactory(nf), - Sets.newHashSet(TaskConfig.KEY_TYPE)); + ImmutableSet.of(TaskConfig.KEY_TYPE)); } protected class Loader { @@ -287,6 +295,18 @@ } /** + * Returns expanded object if property found in the fieldName Field if it is a String, or in the + * List's Strings if it is a List. Returns same object if no expansions occurred. + */ + public <T> T expand(CopyOnWrite<T> cow, String fieldName) { + try { + return expand(cow, cow.getOriginal().getClass().getField(fieldName)); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + /** * Returns expanded object if property found in the Field if it is a String, or in the List's * Strings if it is a List. Returns same object if no expansions occurred. */