Merge "Add a BeanParseListener interface to DynamicOptions."

This commit is contained in:
Martin Fick
2017-04-11 19:23:11 +00:00
committed by Gerrit Code Review
3 changed files with 74 additions and 17 deletions

View File

@@ -17,7 +17,11 @@ package com.google.gerrit.server;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.util.cli.CmdLineParser;
import com.google.inject.Provider;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
/** Helper class to define and parse options from plugins on ssh and RestAPI commands. */
public class DynamicOptions {
/**
* To provide additional options, bind a DynamicBean. For example:
@@ -43,6 +47,16 @@ public class DynamicOptions {
*/
public interface DynamicBean {}
/**
* Implement this if your DynamicBean needs an opportunity to act on the Bean directly before or
* after argument parsing.
*/
public interface BeanParseListener extends DynamicBean {
void onBeanParseStart(String plugin, Object bean);
void onBeanParseEnd(String plugin, Object bean);
}
/**
* The entity which provided additional options may need a way to receive a reference to the
* DynamicBean it provided. To do so, the existing class should implement BeanReceiver (a setter)
@@ -66,32 +80,67 @@ public class DynamicOptions {
void setDynamicBean(String plugin, DynamicBean dynamicBean);
}
Object bean;
Map<String, DynamicBean> beansByPlugin;
/**
* To include options from DynamicBeans, setup a DynamicMap and call this parse method. For
* example:
* Internal: For Gerrit to include options from DynamicBeans, setup a DynamicMap and instantiate
* this class so the following methods can be called if desired:
*
* <pre>
* DynamicMap.mapOf(binder(), DynamicOptions.DynamicBean.class);
* DynamicOptions pluginOptions = new DynamicOptions(bean, dynamicBeans);
* pluginOptions.parseDynamicBeans(clp);
* pluginOptions.setDynamicBeans();
* pluginOptions.onBeanParseStart();
*
* ...
* // parse arguments here: clp.parseArgument(argv);
*
* protected void parseCommandLine(Object options) throws UnloggedFailure {
* final CmdLineParser clp = newCmdLineParser(options);
* DynamicOptions.parse(dynamicBeans, clp, options);
* ...
* }
* pluginOptions.onBeanParseEnd();
* </pre>
*/
public static void parse(DynamicMap<DynamicBean> dynamicBeans, CmdLineParser clp, Object bean) {
public DynamicOptions(Object bean, DynamicMap<DynamicBean> dynamicBeans) {
this.bean = bean;
beansByPlugin = new HashMap<String, DynamicBean>();
for (String plugin : dynamicBeans.plugins()) {
Provider<DynamicBean> provider =
dynamicBeans.byPlugin(plugin).get(bean.getClass().getCanonicalName());
if (provider != null) {
DynamicBean dynamicBean = provider.get();
clp.parseWithPrefix(plugin, dynamicBean);
if (bean instanceof BeanReceiver) {
((BeanReceiver) bean).setDynamicBean(plugin, dynamicBean);
}
beansByPlugin.put(plugin, provider.get());
}
}
}
public void parseDynamicBeans(CmdLineParser clp) {
for (Entry<String, DynamicBean> e : beansByPlugin.entrySet()) {
clp.parseWithPrefix(e.getKey(), e.getValue());
}
}
public void setDynamicBeans() {
if (bean instanceof BeanReceiver) {
BeanReceiver receiver = (BeanReceiver) bean;
for (Entry<String, DynamicBean> e : beansByPlugin.entrySet()) {
receiver.setDynamicBean(e.getKey(), e.getValue());
}
}
}
public void onBeanParseStart() {
for (Entry<String, DynamicBean> e : beansByPlugin.entrySet()) {
DynamicBean instance = e.getValue();
if (instance instanceof BeanParseListener) {
BeanParseListener listener = (BeanParseListener) instance;
listener.onBeanParseStart(e.getKey(), bean);
}
}
}
public void onBeanParseEnd() {
for (Entry<String, DynamicBean> e : beansByPlugin.entrySet()) {
DynamicBean instance = e.getValue();
if (instance instanceof BeanParseListener) {
BeanParseListener listener = (BeanParseListener) instance;
listener.onBeanParseEnd(e.getKey(), bean);
}
}
}