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

org.apache.camel.language.jq.JqFunctions Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.language.jq;

import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.NullNode;
import com.fasterxml.jackson.databind.node.TextNode;
import net.thisptr.jackson.jq.BuiltinFunctionLoader;
import net.thisptr.jackson.jq.Expression;
import net.thisptr.jackson.jq.Function;
import net.thisptr.jackson.jq.PathOutput;
import net.thisptr.jackson.jq.Scope;
import net.thisptr.jackson.jq.Version;
import net.thisptr.jackson.jq.Versions;
import net.thisptr.jackson.jq.exception.JsonQueryException;
import net.thisptr.jackson.jq.internal.tree.FunctionCall;
import net.thisptr.jackson.jq.path.Path;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class JqFunctions {

    public static final ThreadLocal EXCHANGE_LOCAL = new ThreadLocal<>();

    private static final Logger LOGGER = LoggerFactory.getLogger(JqFunctions.class);

    private JqFunctions() {
    }

    public static void load(CamelContext camelContext, Scope scope) {
        Map fromServiceLoader = BuiltinFunctionLoader.getInstance()
                .loadFunctionsFromServiceLoader(
                        camelContext.getApplicationContextClassLoader() != null
                                ? camelContext.getApplicationContextClassLoader()
                                : BuiltinFunctionLoader.class.getClassLoader(),
                        Versions.JQ_1_6);

        Map fromJq = BuiltinFunctionLoader.getInstance()
                .loadFunctionsFromJsonJq(
                        camelContext.getApplicationContextClassLoader() != null
                                ? camelContext.getApplicationContextClassLoader()
                                : BuiltinFunctionLoader.class.getClassLoader(),
                        Versions.JQ_1_6,
                        scope);

        if (fromServiceLoader != null) {
            LOGGER.debug("Loading {} jq functions from ServiceLoader", fromServiceLoader.size());
            fromServiceLoader.forEach(scope::addFunction);
        }

        if (fromJq != null) {
            LOGGER.debug("Loading {} jq functions from Json JQ", fromJq.size());
            fromJq.forEach(scope::addFunction);
        }
    }

    public static void loadFromRegistry(CamelContext camelContext, Scope scope) {
        Map fromRegistry = camelContext.getRegistry().findByTypeWithName(Function.class);
        if (fromRegistry != null) {
            LOGGER.debug("Loading {} jq functions from Registry", fromRegistry.size());
            fromRegistry.forEach(scope::addFunction);
        }
    }

    public static void loadLocal(Scope scope) {
        scope.addFunction(Header.NAME, 1, new Header());
        scope.addFunction(Header.NAME, 2, new Header());
        scope.addFunction(Property.NAME, 1, new Property());
        scope.addFunction(Property.NAME, 2, new Property());
        scope.addFunction(Constant.NAME, 1, new Constant());
        scope.addFunction(Constant.NAME, 2, new Constant());
    }

    public abstract static class ExchangeAwareFunction implements Function {

        @Override
        public void apply(Scope scope, List args, JsonNode in, Path path, PathOutput output, Version version)
                throws JsonQueryException {

            Exchange exchange = EXCHANGE_LOCAL.get();

            if (exchange != null) {
                doApply(scope, args, in, path, output, version, exchange);
            }
        }

        protected abstract void doApply(
                Scope scope,
                List args,
                JsonNode in,
                Path path,
                PathOutput output,
                Version version,
                Exchange exchange)
                throws JsonQueryException;
    }

    /**
     * A function that allow to retrieve an {@link org.apache.camel.Message} header value as part of JQ expression
     * evaluation.
     *
     * As example, the following JQ expression sets the {@code .name} property to the value of the header named
     * {@code CommitterName}.
     *
     * 
     * {@code
     * .name = header(\"CommitterName\")"
     * }
     * 
* */ public static class Header extends ExchangeAwareFunction { public static final String NAME = "header"; @Override protected void doApply( Scope scope, List args, JsonNode in, Path path, PathOutput output, Version version, Exchange exchange) throws JsonQueryException { args.get(0).apply(scope, in, name -> { if (args.size() == 2) { args.get(1).apply(scope, in, defval -> { extract( exchange, name.asText(), defval.asText(), output); }); } else { extract( exchange, name.asText(), null, output); } }); } private void extract(Exchange exchange, String headerName, String headerValue, PathOutput output) throws JsonQueryException { String header = exchange.getMessage().getHeader(headerName, headerValue, String.class); if (header == null) { output.emit(NullNode.getInstance(), null); } else { output.emit(new TextNode(header), null); } } } /** * A function that allow to retrieve an {@link org.apache.camel.Message} property value as part of JQ expression * evaluation. * * As example, the following JQ expression sets the {@code .name} property to the value of the header named * {@code CommitterName}. * *
     * {@code
     * .name = property(\"CommitterName\")"
     * }
     * 
* */ public static class Property extends ExchangeAwareFunction { public static final String NAME = "property"; @Override protected void doApply( Scope scope, List args, JsonNode in, Path path, PathOutput output, Version version, Exchange exchange) throws JsonQueryException { args.get(0).apply(scope, in, name -> { if (args.size() == 2) { args.get(1).apply(scope, in, defval -> { extract( exchange, name.asText(), defval.asText(), output); }); } else { extract( exchange, name.asText(), null, output); } }); } private void extract(Exchange exchange, String propertyName, String propertyValue, PathOutput output) throws JsonQueryException { String header = exchange.getProperty(propertyName, propertyValue, String.class); if (header == null) { output.emit(NullNode.getInstance(), null); } else { output.emit(new TextNode(header), null); } } } /** * A function that returns a constant value as part of JQ expression evaluation. * * As example, the following JQ expression sets the {@code .name} property to the constant value Donald. * *
     * {@code
     * .name = constant(\"Donald\")"
     * }
     * 
* */ public static class Constant implements Function { public static final String NAME = "constant"; @Override public void apply(Scope scope, List args, JsonNode in, Path path, PathOutput output, Version version) throws JsonQueryException { FunctionCall fc = (FunctionCall) args.get(0); String t = fc.toString(); output.emit(new TextNode(t), null); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy