All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.api.jsonata4java.Expression Maven / Gradle / Ivy

There is a newer version: 2.5.1
Show newest version
/**
 * 
 */
package com.api.jsonata4java;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.api.jsonata4java.expressions.EvaluateException;
import com.api.jsonata4java.expressions.EvaluateRuntimeException;
import com.api.jsonata4java.expressions.Expressions;
import com.api.jsonata4java.expressions.ExpressionsVisitor;
import com.api.jsonata4java.expressions.FrameEnvironment;
import com.api.jsonata4java.expressions.ParseException;
import com.api.jsonata4java.expressions.functions.DeclaredFunction;
import com.api.jsonata4java.expressions.generated.MappingExpressionParser.ExprContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.TextNode;

/**
 * Class to provide embedding and extending JSONata features
 */
public class Expression {

   /**
    * Genearte a new Expression based on evaluating the supplied expression
    * 
    * @param expression
    *                   the logic to be parsed for later execution via the evaluate
    *                   methods
    * @return new Expression object
    * @throws ParseException
    * @throws IOException 
    */
   public static Expression jsonata(String expression) throws ParseException, IOException {
      return new Expression(expression);
   }

   /**
    * Testing the various methods based on
    * https://docs.jsonata.org/embedding-extending#expressionregisterfunctionname-implementation-signature
    * 
    * @param args
    *             not used
    */
   public static void main(String[] args) {
      try {
         String exprString = "$sum(example.value)";
         String inputString = "{\"example\": [{\"value\": 4}, {\"value\": 7}, {\"value\": 13}]}";
         System.out.println("Expression is " + exprString);
         System.out.println("Input is " + inputString);
         Expression expression = Expression.jsonata(exprString);
         JsonNode obj = new ObjectMapper().readTree(inputString);
         JsonNode result = expression.evaluate(obj);
         System.out.println("Result is " + result);

         expression = Expression.jsonata("$a +$b()");
         expression.assign("a", "4");
         expression.assign("$b", "function(){1}");
         result = expression.evaluate(obj);
         System.out.println("Input is \"$a + $b()\" with assignments \"a\":4, \"$b\":\"function(){1}\"");
         System.out.println("Result is " + result);

         JsonNode bindingObj = new ObjectMapper().readTree("{\"a\":4, \"b\":\"function(){78}\"}");
         System.out.println("Input is \"$a + $b()\" with binding object: " + bindingObj.toString());
         System.out.println("Result is " + Expression.jsonata("$a + $b()").evaluate(obj, bindingObj));

         bindingObj = new ObjectMapper().readTree("{\"a\":4, \"b\":\"function($c){$c+78}\",\"c\":7}");
         System.out.println("Input is \"$a + $b($c)\" with binding object: " + bindingObj.toString());
         System.out.println("Result is " + Expression.jsonata("$a + $b($c)").evaluate(obj, bindingObj));
         try {
            expression = Expression.jsonata("$notafunction()");
            result = expression.evaluate(JsonNodeFactory.instance.objectNode());
            throw new Exception("Expression " + expression + " should have generated an exception");
         } catch (EvaluateRuntimeException ere) {
            System.out
                  .println("Result is we got the expected EvaluateRuntimeException for " + ere.getLocalizedMessage());
         }
      } catch (ParseException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } catch (EvaluateException e) {
         e.printStackTrace();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

   ExpressionsVisitor _eval = null;
   Expressions _expr = null;
   FrameEnvironment _environment = new FrameEnvironment(null);
   Map _declaredFunctionMap = new HashMap();
   Map _variableMap = new HashMap();

   /**
    * Constructor for Expression
    * 
    * @param expression
    *                   the logic to be parsed for later execution via evaluate
    *                   methods
    * @throws ParseException
    * @throws IOException 
    */
   public Expression(String expression) throws ParseException, IOException {
      _expr = Expressions.parse(expression);
      _eval = _expr.getExpr();
   }

   /**
    * Assign the binding to the environment preparing for evaluation
    * 
    * @param binding
    */
   public void assign(Binding binding) {
      if (binding.getType() == BindingType.VARIABLE) {
         _variableMap.put(binding.getVarName(), binding.getExpression());
      } else {
         _declaredFunctionMap.put(binding.getVarName(), binding.getFunction());
      }
   }

   /**
    * Assign the expression (variable or function declaration) to the variable name
    * supplied
    * 
    * @param varname
    *                   name of the variable to map to a variable expression or
    *                   function declaration expression
    * @param expression
    *                   logic to be assigned to the variable name
    * @throws ParseException
    * @throws IOException 
    */
   public void assign(String varname, String expression) throws ParseException, IOException {
      Binding binding = new Binding(varname, expression);
      assign(binding);
   }

   /**
    * Generate a result form the Expression's parsed expression and variable
    * assignments or registered functions
    * 
    * @param rootContext
    *                    JSON object specifying the content used to evaluate the
    *                    expression
    * @return the result from executing the Expression's parsed expression and
    *         variable assignments or registered functions
    * @throws EvaluateException
    * @throws ParseException
    */
   public JsonNode evaluate(JsonNode rootContext) throws EvaluateException, ParseException {
      ExpressionsVisitor eval = new ExpressionsVisitor(rootContext,new FrameEnvironment(null));
      // process any stored bindings
      for (Iterator it = _variableMap.keySet().iterator(); it.hasNext();) {
         String key = it.next();
         ExprContext ctx = _variableMap.get(key);
         eval.setVariable(key, eval.visit(ctx));
      }
      for (Iterator it = _declaredFunctionMap.keySet().iterator(); it.hasNext();) {
         String key = it.next();
         DeclaredFunction fct = _declaredFunctionMap.get(key);
         eval.setDeclaredFunction(key, fct);
      }
      return eval.visit(_expr.getTree());
   }

   /**
    * Generate a result form the Expression's parsed expression and variable
    * assignments or registered functions specified in the list of bindings
    * 
    * @param rootContext
    *                    JSON object specifying the content used to evaluate the
    *                    expression
    * @param bindings
    *                    assignments of variable names to variable expressions or
    *                    function declarations
    * @return the result from executing the Expression's parsed expression and
    *         variable assignments or registered functions specified in the list of
    *         bindings
    * @throws EvaluateException
    * @throws ParseException
    */
   public JsonNode evaluate(JsonNode rootContext, List bindings) throws EvaluateException, ParseException {
      JsonNode result = null;
      // first do variables
      for (Binding binding : bindings) {
         assign(binding);
      }
      result = evaluate(rootContext);
      return result;
   }

   /**
    * Generate a result form the Expression's parsed expression and variable
    * assignments or registered functions specified in the bindings object
    * 
    * @param rootContext
    *                    JSON object specifying the content used to evaluate the
    *                    expression
    * @param bindingObj
    *                    a JSON object containing the assignments of variable names
    *                    to variable expressions or function declarations
    * @return the result from executing the Expression's parsed expression and
    *         variable assignments or registered functions specified in the
    *         bindings object
    * @throws EvaluateException
    * @throws ParseException
    * @throws IOException 
    */
   public JsonNode evaluate(JsonNode rootContext, JsonNode bindingObj) throws EvaluateException, ParseException, IOException {
      List bindings = new ArrayList();
      for (Iterator it = bindingObj.fieldNames(); it.hasNext();) {
         String key = it.next();
         Object testObj = bindingObj.get(key);
         String expression = "";
         if (testObj instanceof TextNode == false) {
            expression = testObj.toString();
         } else {
            expression = ((TextNode) testObj).asText();
         }
         Binding binding = new Binding(key, expression);
         bindings.add(binding);
      }
      return evaluate(rootContext, bindings);
   }

   /**
    * Registers a function implementation (declaration) by name
    * 
    * @param fctName
    *                       the name of the function
    * @param implementation
    *                       the function declaration
    * @throws ParseException
    * @throws IOException 
    */
   public void registerFunction(String fctName, String implementation) throws ParseException, IOException {
      Binding fctBinding = new Binding(fctName, implementation);
      _declaredFunctionMap.put(fctBinding.getVarName(), fctBinding.getFunction());
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy