Allow plugins to define 'has' search operands.
Create a ChangeHasOperandFactory interface which extends a more generic ChangeOperandFactory in the ChangeQueryBuilder class along with support methods and enhancements to support defining has operands that will be called from the 'has' operator in the ChangeQueryBuilder class. Change-Id: I9014b0094a9d79c2cbcafb0dcd375fbb93a46748
This commit is contained in:

committed by
Martin Fick

parent
01d42968a5
commit
dba4e892b1
@@ -684,6 +684,43 @@ public class SampleOperator
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
[[search_operands]]
|
||||||
|
=== Search Operands ===
|
||||||
|
|
||||||
|
Plugins can define new search operands to extend change searching.
|
||||||
|
Plugin methods implementing search operands (returning a
|
||||||
|
`Predicate<ChangeData>`), must be defined on a class implementing
|
||||||
|
one of the `ChangeQueryBuilder.ChangeOperandsFactory` interfaces
|
||||||
|
(.e.g., ChangeQueryBuilder.ChangeHasOperandFactory). The specific
|
||||||
|
`ChangeOperandFactory` class must also be bound to the `DynamicSet` from
|
||||||
|
a module's `configure()` method in the plugin.
|
||||||
|
|
||||||
|
The new operand, when used in a search would appear as:
|
||||||
|
operatorName:operandName_pluginName
|
||||||
|
|
||||||
|
A sample `ChangeHasOperandFactory` class implementing, and registering, a
|
||||||
|
new `has:sample_pluginName` operand is shown below:
|
||||||
|
|
||||||
|
====
|
||||||
|
@Singleton
|
||||||
|
public class SampleHasOperand implements ChangeHasOperandFactory {
|
||||||
|
public static class Module extends AbstractModule {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(ChangeHasOperandFactory.class)
|
||||||
|
.annotatedWith(Exports.named("sample")
|
||||||
|
.to(SampleHasOperand.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate<ChangeData> create(ChangeQueryBuilder builder)
|
||||||
|
throws QueryParseException {
|
||||||
|
return new HasSamplePredicate();
|
||||||
|
}
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
[[simple-configuration]]
|
[[simple-configuration]]
|
||||||
== Simple Configuration in `gerrit.config`
|
== Simple Configuration in `gerrit.config`
|
||||||
|
|
||||||
|
@@ -376,6 +376,7 @@ public class GerritGlobalModule extends FactoryModule {
|
|||||||
DynamicSet.setOf(binder(), UploadValidationListener.class);
|
DynamicSet.setOf(binder(), UploadValidationListener.class);
|
||||||
|
|
||||||
DynamicMap.mapOf(binder(), ChangeQueryBuilder.ChangeOperatorFactory.class);
|
DynamicMap.mapOf(binder(), ChangeQueryBuilder.ChangeOperatorFactory.class);
|
||||||
|
DynamicMap.mapOf(binder(), ChangeQueryBuilder.ChangeHasOperandFactory.class);
|
||||||
install(new GitwebConfig.LegacyModule(cfg));
|
install(new GitwebConfig.LegacyModule(cfg));
|
||||||
|
|
||||||
bind(AnonymousUser.class);
|
bind(AnonymousUser.class);
|
||||||
|
@@ -28,6 +28,7 @@ import com.google.gerrit.common.data.GroupReference;
|
|||||||
import com.google.gerrit.common.data.SubmitRecord;
|
import com.google.gerrit.common.data.SubmitRecord;
|
||||||
import com.google.gerrit.common.errors.NotSignedInException;
|
import com.google.gerrit.common.errors.NotSignedInException;
|
||||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||||
|
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||||
import com.google.gerrit.reviewdb.client.Branch;
|
import com.google.gerrit.reviewdb.client.Branch;
|
||||||
@@ -98,6 +99,27 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
extends OperatorFactory<ChangeData, ChangeQueryBuilder> {
|
extends OperatorFactory<ChangeData, ChangeQueryBuilder> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a operand (operator value) passed to an operator into a
|
||||||
|
* {@link Predicate}.
|
||||||
|
*
|
||||||
|
* Register a ChangeOperandFactory in a config Module like this (note, for
|
||||||
|
* an example we are using the has predicate, when other predicate plugin
|
||||||
|
* operands are created they can be registered in a similar manner):
|
||||||
|
*
|
||||||
|
* bind(ChangeHasOperandFactory.class)
|
||||||
|
* .annotatedWith(Exports.named("your has operand"))
|
||||||
|
* .to(YourClass.class);
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private interface ChangeOperandFactory {
|
||||||
|
Predicate<ChangeData> create(ChangeQueryBuilder builder)
|
||||||
|
throws QueryParseException;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ChangeHasOperandFactory extends ChangeOperandFactory {
|
||||||
|
}
|
||||||
|
|
||||||
private static final Pattern PAT_LEGACY_ID = Pattern.compile("^[1-9][0-9]*$");
|
private static final Pattern PAT_LEGACY_ID = Pattern.compile("^[1-9][0-9]*$");
|
||||||
private static final Pattern PAT_CHANGE_ID = Pattern.compile(CHANGE_ID_PATTERN);
|
private static final Pattern PAT_CHANGE_ID = Pattern.compile(CHANGE_ID_PATTERN);
|
||||||
private static final Pattern DEF_CHANGE = Pattern.compile(
|
private static final Pattern DEF_CHANGE = Pattern.compile(
|
||||||
@@ -166,6 +188,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
final Provider<InternalChangeQuery> queryProvider;
|
final Provider<InternalChangeQuery> queryProvider;
|
||||||
final ChangeIndexRewriter rewriter;
|
final ChangeIndexRewriter rewriter;
|
||||||
final DynamicMap<ChangeOperatorFactory> opFactories;
|
final DynamicMap<ChangeOperatorFactory> opFactories;
|
||||||
|
final DynamicMap<ChangeHasOperandFactory> hasOperands;
|
||||||
final IdentifiedUser.GenericFactory userFactory;
|
final IdentifiedUser.GenericFactory userFactory;
|
||||||
final CapabilityControl.Factory capabilityControlFactory;
|
final CapabilityControl.Factory capabilityControlFactory;
|
||||||
final ChangeControl.GenericFactory changeControlGenericFactory;
|
final ChangeControl.GenericFactory changeControlGenericFactory;
|
||||||
@@ -199,6 +222,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
Provider<InternalChangeQuery> queryProvider,
|
Provider<InternalChangeQuery> queryProvider,
|
||||||
ChangeIndexRewriter rewriter,
|
ChangeIndexRewriter rewriter,
|
||||||
DynamicMap<ChangeOperatorFactory> opFactories,
|
DynamicMap<ChangeOperatorFactory> opFactories,
|
||||||
|
DynamicMap<ChangeHasOperandFactory> hasOperands,
|
||||||
IdentifiedUser.GenericFactory userFactory,
|
IdentifiedUser.GenericFactory userFactory,
|
||||||
Provider<CurrentUser> self,
|
Provider<CurrentUser> self,
|
||||||
CapabilityControl.Factory capabilityControlFactory,
|
CapabilityControl.Factory capabilityControlFactory,
|
||||||
@@ -224,11 +248,9 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
StarredChangesUtil starredChangesUtil,
|
StarredChangesUtil starredChangesUtil,
|
||||||
AccountCache accountCache,
|
AccountCache accountCache,
|
||||||
@GerritServerConfig Config cfg) {
|
@GerritServerConfig Config cfg) {
|
||||||
this(db, queryProvider, rewriter, opFactories, userFactory, self,
|
this(db, queryProvider, rewriter, opFactories, hasOperands, userFactory,
|
||||||
capabilityControlFactory, changeControlGenericFactory, notesFactory,
|
self, capabilityControlFactory, changeControlGenericFactory, notesFactory, changeDataFactory, fillArgs, commentsUtil,
|
||||||
changeDataFactory, fillArgs, commentsUtil, accountResolver, groupBackend,
|
accountResolver, groupBackend, allProjectsName, allUsersName, patchListCache, repoManager, projectCache, listChildProjects, submitDryRun, conflictsCache,
|
||||||
allProjectsName, allUsersName, patchListCache, repoManager,
|
|
||||||
projectCache, listChildProjects, submitDryRun, conflictsCache,
|
|
||||||
trackingFooters, indexes != null ? indexes.getSearchIndex() : null,
|
trackingFooters, indexes != null ? indexes.getSearchIndex() : null,
|
||||||
indexConfig, listMembers, starredChangesUtil, accountCache,
|
indexConfig, listMembers, starredChangesUtil, accountCache,
|
||||||
cfg == null ? true : cfg.getBoolean("change", "allowDrafts", true));
|
cfg == null ? true : cfg.getBoolean("change", "allowDrafts", true));
|
||||||
@@ -239,6 +261,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
Provider<InternalChangeQuery> queryProvider,
|
Provider<InternalChangeQuery> queryProvider,
|
||||||
ChangeIndexRewriter rewriter,
|
ChangeIndexRewriter rewriter,
|
||||||
DynamicMap<ChangeOperatorFactory> opFactories,
|
DynamicMap<ChangeOperatorFactory> opFactories,
|
||||||
|
DynamicMap<ChangeHasOperandFactory> hasOperands,
|
||||||
IdentifiedUser.GenericFactory userFactory,
|
IdentifiedUser.GenericFactory userFactory,
|
||||||
Provider<CurrentUser> self,
|
Provider<CurrentUser> self,
|
||||||
CapabilityControl.Factory capabilityControlFactory,
|
CapabilityControl.Factory capabilityControlFactory,
|
||||||
@@ -293,15 +316,16 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
this.starredChangesUtil = starredChangesUtil;
|
this.starredChangesUtil = starredChangesUtil;
|
||||||
this.accountCache = accountCache;
|
this.accountCache = accountCache;
|
||||||
this.allowsDrafts = allowsDrafts;
|
this.allowsDrafts = allowsDrafts;
|
||||||
|
this.hasOperands = hasOperands;
|
||||||
}
|
}
|
||||||
|
|
||||||
Arguments asUser(CurrentUser otherUser) {
|
Arguments asUser(CurrentUser otherUser) {
|
||||||
return new Arguments(db, queryProvider, rewriter, opFactories, userFactory,
|
return new Arguments(db, queryProvider, rewriter, opFactories,
|
||||||
Providers.of(otherUser),
|
hasOperands, userFactory, Providers.of(otherUser),
|
||||||
capabilityControlFactory, changeControlGenericFactory, notesFactory,
|
capabilityControlFactory, changeControlGenericFactory, notesFactory,
|
||||||
changeDataFactory, fillArgs, commentsUtil, accountResolver, groupBackend,
|
changeDataFactory, fillArgs, commentsUtil, accountResolver,
|
||||||
allProjectsName, allUsersName, patchListCache, repoManager,
|
groupBackend, allProjectsName, allUsersName, patchListCache,
|
||||||
projectCache, listChildProjects, submitDryRun,
|
repoManager, projectCache, listChildProjects, submitDryRun,
|
||||||
conflictsCache, trackingFooters, index, indexConfig, listMembers,
|
conflictsCache, trackingFooters, index, indexConfig, listMembers,
|
||||||
starredChangesUtil, accountCache, allowsDrafts);
|
starredChangesUtil, accountCache, allowsDrafts);
|
||||||
}
|
}
|
||||||
@@ -453,6 +477,16 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
if ("edit".equalsIgnoreCase(value)) {
|
if ("edit".equalsIgnoreCase(value)) {
|
||||||
return new EditByPredicate(self());
|
return new EditByPredicate(self());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for plugins the value will be operandName_pluginName
|
||||||
|
String[] names = value.split("_");
|
||||||
|
if (names.length == 2) {
|
||||||
|
ChangeHasOperandFactory op = args.hasOperands.get(names[1], names[0]);
|
||||||
|
if (op != null) {
|
||||||
|
return op.create(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user