org.apache.camel.language.jq.JqExpression Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of camel-jq Show documentation
Show all versions of camel-jq Show documentation
Java expression language using JQ
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.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.BooleanNode;
import net.thisptr.jackson.jq.JsonQuery;
import net.thisptr.jackson.jq.Scope;
import net.thisptr.jackson.jq.Versions;
import net.thisptr.jackson.jq.exception.JsonQueryException;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Expression;
import org.apache.camel.ExpressionIllegalSyntaxException;
import org.apache.camel.InvalidPayloadException;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.TypeConverter;
import org.apache.camel.spi.ExpressionResultTypeAware;
import org.apache.camel.support.ExpressionAdapter;
import org.apache.camel.support.MessageHelper;
import org.apache.camel.support.builder.ExpressionBuilder;
public class JqExpression extends ExpressionAdapter implements ExpressionResultTypeAware {
private final String expression;
private Scope scope;
private String resultTypeName;
private Class> resultType;
private JsonQuery query;
private TypeConverter typeConverter;
private Expression source;
public JqExpression(String expression) {
this(null, expression);
}
public JqExpression(Scope scope, String expression) {
this.scope = scope;
this.expression = expression;
}
@Override
public void init(CamelContext camelContext) {
// avoid initializing multiple times
if (this.query == null) {
super.init(camelContext);
if (this.scope == null) {
JqLanguage lan = (JqLanguage) camelContext.resolveLanguage("jq");
this.scope = Scope.newChildScope(lan.getRootScope());
}
this.typeConverter = camelContext.getTypeConverter();
try {
this.query = JsonQuery.compile(this.expression, Versions.JQ_1_6);
} catch (JsonQueryException e) {
throw new ExpressionIllegalSyntaxException(this.expression, e);
}
if (resultTypeName != null && (resultType == null || resultType == Object.class)) {
resultType = camelContext.getClassResolver().resolveClass(resultTypeName);
}
if (resultType == null || resultType == Object.class) {
resultType = JsonNode.class;
}
}
if (this.source == null) {
source = ExpressionBuilder.bodyExpression();
}
}
public Scope getScope() {
return scope;
}
public void setScope(Scope scope) {
this.scope = scope;
}
@Override
public String getExpressionText() {
return this.expression;
}
@Override
public Class> getResultType() {
return this.resultType;
}
public void setResultType(Class> resultType) {
this.resultType = resultType;
}
public String getResultTypeName() {
return resultTypeName;
}
public void setResultTypeName(String resultTypeName) {
this.resultTypeName = resultTypeName;
}
public Expression getSource() {
return source;
}
public void setSource(Expression source) {
this.source = source;
}
@Override
public boolean matches(Exchange exchange) {
final Object value = evaluate(exchange, Object.class);
if (value instanceof BooleanNode) {
return ((BooleanNode) value).asBoolean();
}
if (value instanceof Collection) {
return !((Collection>) value).isEmpty();
}
return false;
}
@Override
public Object evaluate(Exchange exchange) {
if (this.query == null) {
return null;
}
try {
JqFunctions.EXCHANGE_LOCAL.set(exchange);
final List outputs = new ArrayList<>(1);
final JsonNode payload = getPayload(exchange);
this.query.apply(scope, payload, outputs::add);
if (outputs.size() == 1) {
JsonNode out = outputs.get(0);
// special if null
if (out.isNull()) {
return null;
}
// no need to convert output
if (resultType == JsonNode.class) {
return out;
}
return this.typeConverter.convertTo(resultType, exchange, outputs.get(0));
} else if (outputs.size() > 1) {
// no need to convert outputs
if (resultType == JsonNode.class) {
return outputs;
}
return outputs.stream()
.filter(o -> !o.isNull()) // skip null
.map(item -> this.typeConverter.convertTo(resultType, exchange, item))
.collect(Collectors.toList());
}
} catch (Exception e) {
throw new RuntimeCamelException(e);
} finally {
JqFunctions.EXCHANGE_LOCAL.remove();
}
return null;
}
/**
* Determines the payload by looking at heders, properties and finally the payload.
*
* @param exchange the {@link Exchange} being processed
* @return the {@link JsonNode} to be processed by the expression
*/
private JsonNode getPayload(Exchange exchange) throws Exception {
JsonNode payload = source.evaluate(exchange, JsonNode.class);
// if body is stream cached then reset, so we can re-read it again
MessageHelper.resetStreamCache(exchange.getMessage());
if (payload == null) {
throw new InvalidPayloadException(exchange, JsonNode.class);
}
return payload;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy