### Question:
ActionParameterEnricher extends BaseParameterEnricher { @Override public Map<String, String> onParameterAnnotation(final String parameterName, final Type parameterType, final Annotation annotation) { final Class<? extends Annotation> annotationType = annotation.annotationType(); final ActionRef ref = annotationType.getAnnotation(ActionRef.class); if (ref == null) { return emptyMap(); } final Class<?> actionType = ref.value(); if (actionType == Object.class) { return singletonMap( META_PREFIX + clientActionsMapping.computeIfAbsent(annotationType.getSimpleName(), this::toSnakeCase), getClientActionName(annotation)); } final String type = actionType.getAnnotation(ActionType.class).value(); return new HashMap<String, String>() { { put(META_PREFIX + type, getValueString(ref.ref(), annotation)); ofNullable(getParametersString(annotation)).ifPresent(v -> put(META_PREFIX + type + "::parameters", v)); Stream .of(annotationType.getMethods()) .filter(it -> annotationType == it.getDeclaringClass() && Stream.of("parameters", "value").noneMatch(v -> it.getName().equalsIgnoreCase(v))) .forEach(m -> put(META_PREFIX + type + "::" + m.getName(), getString(m, annotation))); } }; }  @Override Map<String, String> onParameterAnnotation(final String parameterName, final Type parameterType,
            final Annotation annotation); static final String META_PREFIX; }### Answer:
@Test void update() { assertEquals(new HashMap<String, String>() { { put("tcomp::action::update", "test"); put("tcomp::action::update::parameters", ".,foo,/bar/dummy"); put("tcomp::action::update::after", "propertyX"); } }, new ActionParameterEnricher().onParameterAnnotation("testParam", String.class, new Updatable() { @Override public String value() { return "test"; } @Override public String after() { return "propertyX"; } @Override public String[] parameters() { return new String[] { ".", "foo", "/bar/dummy" }; } @Override public Class<? extends Annotation> annotationType() { return Updatable.class; } })); }
@Test void builtInSuggestion() { assertEquals(singletonMap("tcomp::action::built_in_suggestable", "INCOMING_SCHEMA_ENTRY_NAMES"), new ActionParameterEnricher() .onParameterAnnotation("testParam", String.class, new BuiltInSuggestable() { @Override public Name value() { return Name.INCOMING_SCHEMA_ENTRY_NAMES; } @Override public String name() { return ""; } @Override public Class<? extends Annotation> annotationType() { return BuiltInSuggestable.class; } })); }
@Test void builtInSuggestionCustom() { assertEquals(singletonMap("tcomp::action::built_in_suggestable", "alternate"), new ActionParameterEnricher() .onParameterAnnotation("testParam", String.class, new BuiltInSuggestable() { @Override public Name value() { return Name.CUSTOM; } @Override public String name() { return "alternate"; } @Override public Class<? extends Annotation> annotationType() { return BuiltInSuggestable.class; } })); }
@Test void suggestion() { assertEquals(new HashMap<String, String>() { { put("tcomp::action::suggestions", "test"); put("tcomp::action::suggestions::parameters", ".,foo,/bar/dummy"); } }, new ActionParameterEnricher().onParameterAnnotation("testParam", String.class, new Suggestable() { @Override public String value() { return "test"; } @Override public String[] parameters() { return new String[] { ".", "foo", "/bar/dummy" }; } @Override public Class<? extends Annotation> annotationType() { return Suggestable.class; } })); }
@Test void condition() { assertEquals(new HashMap<String, String>() { { put("tcomp::action::dynamic_values", "test"); } }, new ActionParameterEnricher().onParameterAnnotation("testParam", String.class, new Proposable() { @Override public String value() { return "test"; } @Override public Class<? extends Annotation> annotationType() { return Proposable.class; } })); }