diff --git a/README.md b/README.md index ea800db..34cbabd 100644 --- a/README.md +++ b/README.md @@ -457,6 +457,54 @@ public interface LibraryService { ```json {"jsonrpc":"2.0", "method": "VideoLibrary.GetTVShows", "params": { "properties": ["title"] }, "id":1} ``` +#### Fixed parameters + +You may need to pass some fixed parameters to a JsonRpc method. In this case, use the annotation @JsonRpcFixedParam on the service method. You may also use @JsonRpcFixedParams to pass a collection of fixed parameters. + +```java +@JsonRpcService("/jsonrpc") +public interface LibraryService { + @JsonRpcMethod("VideoLibrary.GetTVShows") + @JsonRpcFixedParam(name = "status", value = "published") + List fetchTVShows(@JsonRpcParam(value="properties") final List properties); +} +``` + +```json +{ + "jsonrpc":"2.0", + "method": "VideoLibrary.GetTVShows", + "params": { + "status": "published", + "properties": ["title"] + }, + "id":1 +} +``` + +```java +@JsonRpcService("/jsonrpc") +public interface LibraryService { + @JsonRpcMethod("VideoLibrary.GetTVShows") + @JsonRpcFixedParams(fixedParams = { + @JsonRpcFixedParam(name = "status", value = "published"), + @JsonRpcFixedParam(name = "order_by", value = "recent") }) + List fetchTVShows(@JsonRpcParam(value="properties") final List properties); +} +``` + +```json +{ + "jsonrpc":"2.0", + "method": "VideoLibrary.GetTVShows", + "params": { + "status": "published", + "order_by": "recent", + "properties": ["title"] + }, + "id":1 +} +``` [Google Group]: http://groups.google.com/group/json-rpc [Jackson page]: https://github.com/FasterXML/jackson diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcFixedParam.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcFixedParam.java new file mode 100644 index 0000000..47fae28 --- /dev/null +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcFixedParam.java @@ -0,0 +1,21 @@ +package com.googlecode.jsonrpc4j; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface JsonRpcFixedParam { + + /** + * @return the parameter's name. + */ + String name(); + + /** + * @return the parameter's value. + */ + String value(); +} diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcFixedParams.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcFixedParams.java new file mode 100644 index 0000000..bfeb95d --- /dev/null +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcFixedParams.java @@ -0,0 +1,16 @@ +package com.googlecode.jsonrpc4j; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface JsonRpcFixedParams { + + /** + * @return a fixed parameter's collection. + */ + JsonRpcFixedParam[] fixedParams(); +} diff --git a/src/main/java/com/googlecode/jsonrpc4j/ReflectionUtil.java b/src/main/java/com/googlecode/jsonrpc4j/ReflectionUtil.java index cb8b565..dc95c72 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/ReflectionUtil.java +++ b/src/main/java/com/googlecode/jsonrpc4j/ReflectionUtil.java @@ -194,14 +194,18 @@ public static Object parseArguments(Method method, Object[] arguments) { if (jsonRpcMethod != null) paramsPassMode = jsonRpcMethod.paramsPassMode(); - Map namedParams = getNamedParameters(method, arguments); + Map params = new LinkedHashMap<>(); + + params.putAll(getFixedParametersCollection(method)); + params.putAll(getFixedParameters(method)); + params.putAll(getNamedParameters(method, arguments)); switch (paramsPassMode) { case ARRAY: - if (namedParams.size() > 0) { - Object[] parsed = new Object[namedParams.size()]; + if (params.size() > 0) { + Object[] parsed = new Object[params.size()]; int i = 0; - for (Object value : namedParams.values()) { + for (Object value : params.values()) { parsed[i++] = value; } return parsed; @@ -209,8 +213,8 @@ public static Object parseArguments(Method method, Object[] arguments) { return arguments != null ? arguments : new Object[]{}; } case OBJECT: - if (namedParams.size() > 0) { - return namedParams; + if (params.size() > 0) { + return params; } else { if (arguments == null) { return new Object[]{}; @@ -221,8 +225,8 @@ public static Object parseArguments(Method method, Object[] arguments) { } case AUTO: default: - if (namedParams.size() > 0) { - return namedParams; + if (params.size() > 0) { + return params; } else { return arguments != null ? arguments : new Object[]{}; } @@ -260,6 +264,49 @@ private static Map getNamedParameters(Method method, Object[] ar return namedParams; } + /** + * Checks method for @JsonRpcFixedParam annotations and returns fixed + * parameters. + * + * @param method the method + * @return fixed parameters or empty if no annotations found + */ + public static Map getFixedParameters(Method method) { + + Map fixedParams = new LinkedHashMap<>(); + + for (Annotation an : getAnnotations(method)) { + if (an instanceof JsonRpcFixedParam) { + JsonRpcFixedParam jAnn = (JsonRpcFixedParam) an; + fixedParams.put(jAnn.name(), jAnn.value()); + } + } + + return fixedParams; + } + + /** + * Checks method for @JsonRpcFixedParams annotation and returns fixed + * parameters. + * + * @param method the method + * @return fixed parameters or empty if no annotations found + */ + public static Map getFixedParametersCollection(Method method) { + + Map fixedParams = new LinkedHashMap<>(); + + JsonRpcFixedParams jsonRpcFixedParams = getAnnotation(method, JsonRpcFixedParams.class); + + if (jsonRpcFixedParams != null) { + for (JsonRpcFixedParam fixedParam : jsonRpcFixedParams.fixedParams()) { + fixedParams.put(fixedParam.name(), fixedParam.value()); + } + } + + return fixedParams; + } + public static void clearCache() { methodCache.clear(); parameterTypeCache.clear(); diff --git a/src/test/java/com/googlecode/jsonrpc4j/ReflectionUtilTest.java b/src/test/java/com/googlecode/jsonrpc4j/ReflectionUtilTest.java index d0e1b09..e2f4e21 100644 --- a/src/test/java/com/googlecode/jsonrpc4j/ReflectionUtilTest.java +++ b/src/test/java/com/googlecode/jsonrpc4j/ReflectionUtilTest.java @@ -57,6 +57,35 @@ public void someNamedParamsPassParamsAuto() throws Exception { ReflectionUtil.parseArguments(JsonRpcTestService.class.getMethod("someNamedParamsPassParamsAuto", String.class, int.class), null); } + + @Test + public void fixedParamPassParamsAuto() throws Exception { + Object[] arguments = { "1", 2 }; + + @SuppressWarnings("unchecked") + Map params = (Map) ReflectionUtil.parseArguments( + JsonRpcTestService.class.getMethod("fixedParamPassParamsAuto", String.class, int.class), arguments); + + assertEquals(3, params.size()); + assertEquals("1", params.get("one")); + assertEquals(2, params.get("two")); + assertEquals("value1", params.get("param1")); + } + + @Test + public void fixedParamsPassParamsAuto() throws Exception { + Object[] arguments = { "1", 2 }; + + @SuppressWarnings("unchecked") + Map params = (Map) ReflectionUtil.parseArguments( + JsonRpcTestService.class.getMethod("fixedParamsPassParamsAuto", String.class, int.class), arguments); + + assertEquals(4, params.size()); + assertEquals("1", params.get("one")); + assertEquals(2, params.get("two")); + assertEquals("value1", params.get("param1")); + assertEquals("value2", params.get("param2")); + } @Test public void allNamedParamsPassParamsAuto() throws Exception { @@ -82,6 +111,33 @@ public void someNamedParamsPassParamsArray() throws Exception { ReflectionUtil.parseArguments(JsonRpcTestService.class.getMethod("someNamedParamsPassParamsArray", String.class, int.class), null); } + + @Test + public void fixedParamPassParamsArray() throws Exception { + Object[] arguments = { "1", 2 }; + + Object[] params = (Object[]) ReflectionUtil.parseArguments( + JsonRpcTestService.class.getMethod("fixedParamPassParamsArray", String.class, int.class), arguments); + + assertEquals(3, params.length); + assertEquals("value1", params[0]); + assertEquals("1", params[1]); + assertEquals(2, params[2]); + } + + @Test + public void fixedParamsPassParamsArray() throws Exception { + Object[] arguments = { "1", 2 }; + + Object[] params = (Object[]) ReflectionUtil.parseArguments( + JsonRpcTestService.class.getMethod("fixedParamsPassParamsArray", String.class, int.class), arguments); + + assertEquals(4, params.length); + assertEquals("value1", params[0]); + assertEquals("value2", params[1]); + assertEquals("1", params[2]); + assertEquals(2, params[3]); + } @Test public void allNamedParamsPassParamsArray() throws Exception { @@ -106,6 +162,35 @@ public void someNamedParamsPassParamsObject() throws Exception { ReflectionUtil.parseArguments(JsonRpcTestService.class.getMethod("someNamedParamsPassParamsObject", String.class, int.class), null); } + + @Test + public void fixedParamPassParamsObject() throws Exception { + Object[] arguments = { "1", 2 }; + + @SuppressWarnings("unchecked") + Map params = (Map) ReflectionUtil.parseArguments( + JsonRpcTestService.class.getMethod("fixedParamPassParamsObject", String.class, int.class), arguments); + + assertEquals(3, params.size()); + assertEquals("1", params.get("one")); + assertEquals(2, params.get("two")); + assertEquals("value1", params.get("param1")); + } + + @Test + public void fixedParamsPassParamsObject() throws Exception { + Object[] arguments = { "1", 2 }; + + @SuppressWarnings("unchecked") + Map params = (Map) ReflectionUtil.parseArguments( + JsonRpcTestService.class.getMethod("fixedParamsPassParamsObject", String.class, int.class), arguments); + + assertEquals(4, params.size()); + assertEquals("1", params.get("one")); + assertEquals(2, params.get("two")); + assertEquals("value1", params.get("param1")); + assertEquals("value2", params.get("param2")); + } @Test public void allNamedParamsPassParamsObject() throws Exception { @@ -143,6 +228,15 @@ private interface JsonRpcTestService { @JsonRpcMethod(value = "someNamedParamsPassParamsAuto", paramsPassMode = JsonRpcParamsPassMode.AUTO) void someNamedParamsPassParamsAuto(@JsonRpcParam("one") String one, int two); + @JsonRpcMethod(value = "fixedParamPassParamsAuto", paramsPassMode = JsonRpcParamsPassMode.AUTO) + @JsonRpcFixedParam(name = "param1", value = "value1") + void fixedParamPassParamsAuto(@JsonRpcParam("one") String one, @JsonRpcParam("two") int two); + + @JsonRpcMethod(value = "fixedParamsPassParamsAuto", paramsPassMode = JsonRpcParamsPassMode.AUTO) + @JsonRpcFixedParams(fixedParams = { @JsonRpcFixedParam(name = "param1", value = "value1"), + @JsonRpcFixedParam(name = "param2", value = "value2") }) + void fixedParamsPassParamsAuto(@JsonRpcParam("one") String one, @JsonRpcParam("two") int two); + @JsonRpcMethod(value = "allNamedParamsPassParamsAuto", paramsPassMode = JsonRpcParamsPassMode.AUTO) void allNamedParamsPassParamsAuto(@JsonRpcParam("one") String one, @JsonRpcParam("two") int two); @@ -152,6 +246,15 @@ private interface JsonRpcTestService { @JsonRpcMethod(value = "someNamedParamsPassParamsArray", paramsPassMode = JsonRpcParamsPassMode.ARRAY) void someNamedParamsPassParamsArray(@JsonRpcParam("one") String one, int two); + @JsonRpcMethod(value = "fixedParamPassParamsArray", paramsPassMode = JsonRpcParamsPassMode.ARRAY) + @JsonRpcFixedParam(name = "param1", value = "value1") + void fixedParamPassParamsArray(@JsonRpcParam("one") String one, @JsonRpcParam("two") int two); + + @JsonRpcMethod(value = "fixedParamsPassParamsArray", paramsPassMode = JsonRpcParamsPassMode.ARRAY) + @JsonRpcFixedParams(fixedParams = { @JsonRpcFixedParam(name = "param1", value = "value1"), + @JsonRpcFixedParam(name = "param2", value = "value2") }) + void fixedParamsPassParamsArray(@JsonRpcParam("one") String one, @JsonRpcParam("two") int two); + @JsonRpcMethod(value = "allNamedParamsPassParamsArray", paramsPassMode = JsonRpcParamsPassMode.ARRAY) void allNamedParamsPassParamsArray(@JsonRpcParam("one") String one, @JsonRpcParam("two") int two); @@ -161,6 +264,15 @@ private interface JsonRpcTestService { @JsonRpcMethod(value = "someNamedParamsPassParamsObject", paramsPassMode = JsonRpcParamsPassMode.OBJECT) void someNamedParamsPassParamsObject(@JsonRpcParam("one") String one, int two); + @JsonRpcMethod(value = "fixedParamPassParamsObject", paramsPassMode = JsonRpcParamsPassMode.OBJECT) + @JsonRpcFixedParam(name = "param1", value = "value1") + void fixedParamPassParamsObject(@JsonRpcParam("one") String one, @JsonRpcParam("two") int two); + + @JsonRpcMethod(value = "fixedParamsPassParamsObject", paramsPassMode = JsonRpcParamsPassMode.OBJECT) + @JsonRpcFixedParams(fixedParams = { @JsonRpcFixedParam(name = "param1", value = "value1"), + @JsonRpcFixedParam(name = "param2", value = "value2") }) + void fixedParamsPassParamsObject(@JsonRpcParam("one") String one, @JsonRpcParam("two") int two); + @JsonRpcMethod(value = "allNamedParamsPassParamsObject", paramsPassMode = JsonRpcParamsPassMode.OBJECT) void allNamedParamsPassParamsObject(@JsonRpcParam("one") String one, @JsonRpcParam("two") int two);