Browse Source

adding ability to define Function via the configuration object

pull/354/head
Robert Craig 8 years ago
parent
commit
c7a7ef37c7
  1. 25
      json-path/src/main/java/com/jayway/jsonpath/Configuration.java
  2. 14
      json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java
  3. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/path/FunctionPathToken.java
  4. 60
      json-path/src/test/java/com/jayway/jsonpath/internal/function/FunctionDefinitionTest.java

25
json-path/src/main/java/com/jayway/jsonpath/Configuration.java

@ -15,6 +15,7 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.DefaultsImpl;
import com.jayway.jsonpath.internal.function.PathFunction;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.mapper.MappingProvider;
@ -23,6 +24,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import static com.jayway.jsonpath.internal.Utils.notNull;
@ -55,8 +57,10 @@ public class Configuration {
private final MappingProvider mappingProvider;
private final Set<Option> options;
private final Collection<EvaluationListener> evaluationListeners;
private final Map<String, Class> functionMap;
private Configuration(JsonProvider jsonProvider, MappingProvider mappingProvider, EnumSet<Option> options, Collection<EvaluationListener> evaluationListeners) {
private Configuration(JsonProvider jsonProvider, MappingProvider mappingProvider, EnumSet<Option> options,
Collection<EvaluationListener> evaluationListeners, Map<String, Class> functionMap) {
notNull(jsonProvider, "jsonProvider can not be null");
notNull(mappingProvider, "mappingProvider can not be null");
notNull(options, "setOptions can not be null");
@ -65,6 +69,7 @@ public class Configuration {
this.mappingProvider = mappingProvider;
this.options = Collections.unmodifiableSet(options);
this.evaluationListeners = Collections.unmodifiableCollection(evaluationListeners);
this.functionMap = functionMap;
}
/**
@ -127,6 +132,15 @@ public class Configuration {
return mappingProvider;
}
/**
* Returns {@link com.jayway.jsonpath.internal.function.PathFunction} defined in functionMap.
* @param name
* @return null if there are no functionMap defined or the function is not defined.
*/
public Map<String, Class> getFunctionMap() {
return functionMap;
}
/**
* Creates a new configuration by adding the new options to the options used in this configuration.
* @param options options to add
@ -189,6 +203,8 @@ public class Configuration {
private JsonProvider jsonProvider;
private MappingProvider mappingProvider;
private Map<String, Class> functionMap;
private EnumSet<Option> options = EnumSet.noneOf(Option.class);
private Collection<EvaluationListener> evaluationListener = new ArrayList<EvaluationListener>();
@ -202,6 +218,11 @@ public class Configuration {
return this;
}
public ConfigurationBuilder functionMap(Map<String, Class> functionMap) {
this.functionMap = functionMap;
return this;
}
public ConfigurationBuilder options(Option... flags) {
if(flags.length > 0) {
this.options.addAll(asList(flags));
@ -234,7 +255,7 @@ public class Configuration {
mappingProvider = defaults.mappingProvider();
}
}
return new Configuration(jsonProvider, mappingProvider, options, evaluationListener);
return new Configuration(jsonProvider, mappingProvider, options, evaluationListener, functionMap);
}
}

14
json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java

@ -1,5 +1,6 @@
package com.jayway.jsonpath.internal.function;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.internal.function.json.Append;
import com.jayway.jsonpath.internal.function.numeric.Average;
@ -64,8 +65,17 @@ public class PathFunctionFactory {
*
* @throws InvalidPathException
*/
public static PathFunction newFunction(String name) throws InvalidPathException {
Class functionClazz = FUNCTIONS.get(name);
public static PathFunction newFunction(String name, Configuration conf) throws InvalidPathException {
Class functionClazz = null;
if (conf != null && conf.getFunctionMap() != null) {
Map<String, Class> confFunctionMap = conf.getFunctionMap();
functionClazz = confFunctionMap.get(name);
}
if (functionClazz == null) {
functionClazz = FUNCTIONS.get(name);
}
if(functionClazz == null){
throw new InvalidPathException("Function with name: " + name + " does not exist.");
} else {

2
json-path/src/main/java/com/jayway/jsonpath/internal/path/FunctionPathToken.java

@ -35,7 +35,7 @@ public class FunctionPathToken extends PathToken {
@Override
public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
PathFunction pathFunction = PathFunctionFactory.newFunction(functionName);
PathFunction pathFunction = PathFunctionFactory.newFunction(functionName, ctx.configuration());
evaluateParameters(currentPath, parent, model, ctx);
Object result = pathFunction.invoke(currentPath, parent, model, ctx, functionParams);
ctx.addResult(currentPath + "." + functionName, parent, result);

60
json-path/src/test/java/com/jayway/jsonpath/internal/function/FunctionDefinitionTest.java

@ -0,0 +1,60 @@
package com.jayway.jsonpath.internal.function;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Configurations;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.function.numeric.Max;
import com.jayway.jsonpath.spi.json.GsonJsonProvider;
import com.jayway.jsonpath.spi.mapper.GsonMappingProvider;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class ToLowerPathFunction implements PathFunction {
@Override
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {
return ((String) model).toLowerCase();
}
}
public class FunctionDefinitionTest extends BaseFunctionTest {
@Test
public void testToLowerFunction() throws IllegalAccessException, InstantiationException {
Map<String, Class> funcMap = new HashMap<String, Class>();
funcMap.put("toLower", ToLowerPathFunction.class);
Configuration conf = Configuration
.builder()
.mappingProvider(new GsonMappingProvider())
.jsonProvider(new GsonJsonProvider())
.functionMap(funcMap)
.build();
verifyFunction(conf, "$.upper.toLower()", "{\"upper\":\"UPPERCASE\"}", "uppercase");
}
@Test
public void testUndefinedFunction() throws IllegalAccessException, InstantiationException {
Map<String, Class> funcMap = new HashMap<String, Class>();
funcMap.put("toLower", ToLowerPathFunction.class);
Configuration conf = Configuration
.builder()
.mappingProvider(new GsonMappingProvider())
.jsonProvider(new GsonJsonProvider())
.functionMap(funcMap)
.build();
boolean caughtException = false;
try {
verifyFunction(conf, "$.upper.undefined()", "{\"upper\":\"UPPERCASE\"}", "uppercase");
} catch (InvalidPathException exp) {
caughtException=true;
}
assertThat(caughtException);
}
}
Loading…
Cancel
Save