Skip to content

Commit

Permalink
[KOGITO-9810] Supporting nested properties (apache#3229)
Browse files Browse the repository at this point in the history
* [KOGITO-9810] Supporting nested properties

* Revert "[KOGITO-9810] Supporting nested properties"

This reverts commit 8df264f.

* [KOGITO-9810] Alternative approach

* [KOGITO-9810] Fixing image test
  • Loading branch information
fjtirado authored and rgdoliveira committed Dec 13, 2023
1 parent 994995f commit dfbd63a
Show file tree
Hide file tree
Showing 13 changed files with 245 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.kie.kogito.jackson.utils.FunctionJsonNode;
import org.kie.kogito.jackson.utils.JsonObjectUtils;
import org.kie.kogito.jackson.utils.ObjectMapperFactory;
import org.kie.kogito.jackson.utils.PrefixJsonNode;
import org.kie.kogito.process.expr.Expression;
import org.kie.kogito.serverless.workflow.utils.ExpressionHandlerUtils;
import org.kie.kogito.serverless.workflow.utils.JsonNodeContext;
Expand Down Expand Up @@ -174,7 +175,7 @@ public void assign(Object target, Object value, KogitoProcessContext context) {

private Scope getScope(KogitoProcessContext processInfo) {
Scope childScope = Scope.newChildScope(scope.get());
childScope.setValue(ExpressionHandlerUtils.SECRET_MAGIC, new FunctionJsonNode(ExpressionHandlerUtils::getSecret));
childScope.setValue(ExpressionHandlerUtils.SECRET_MAGIC, new PrefixJsonNode<>(ExpressionHandlerUtils::getOptionalSecret));
childScope.setValue(ExpressionHandlerUtils.CONTEXT_MAGIC, new FunctionJsonNode(ExpressionHandlerUtils.getContextFunction(processInfo)));
childScope.setValue(ExpressionHandlerUtils.CONST_MAGIC, ExpressionHandlerUtils.getConstants(processInfo));
return childScope;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ private static Stream<Arguments> provideMagicWordExpressionsToTest() {
Arguments.of("$SECRET.none", "null", getContext()),
Arguments.of("\"$SECRET.none\"", "$SECRET.none", getContext()),
Arguments.of("$SECRET.lettersonly", "secretlettersonly", getContext()),
Arguments.of("$SECRET.dot.secret", "null", getContext()),
Arguments.of("$SECRET.dot.secret", "secretdotsecret", getContext()),
Arguments.of("$SECRET.\"dot.secret\"", "secretdotsecret", getContext()),
Arguments.of("$SECRET.\"dash-secret\"", "secretdashsecret", getContext()),
Arguments.of("$CONST.someconstant", "value", getContext()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.JsonPathException;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;

public class JsonPathExpression implements Expression {

Expand All @@ -57,7 +56,7 @@ private static final String replaceMagic(String expr, String magic) {
private Configuration getConfiguration(KogitoProcessContext context) {
return Configuration
.builder()
.mappingProvider(new JacksonMappingProvider())
.mappingProvider(new JsonPathJacksonProvider())
.jsonProvider(new WorkflowJacksonJsonNodeJsonProvider(context))
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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.kie.kogito.expr.jsonpath;

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;

public class JsonPathJacksonProvider extends JacksonMappingProvider {

@Override
public <T> T map(Object source, Class<T> targetType, Configuration configuration) {
return targetType.isAssignableFrom(source.getClass()) ? targetType.cast(source) : super.map(source, targetType, configuration);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import java.util.function.Function;

import org.kie.kogito.internal.process.runtime.KogitoProcessContext;
import org.kie.kogito.jackson.utils.FunctionBaseJsonNode;
import org.kie.kogito.jackson.utils.PrefixJsonNode;
import org.kie.kogito.serverless.workflow.utils.ExpressionHandlerUtils;

import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;
Expand All @@ -37,10 +39,12 @@ public WorkflowJacksonJsonNodeJsonProvider(KogitoProcessContext context) {
public Object getMapValue(Object obj, String key) {
if (obj instanceof Function) {
return ((Function<String, Object>) obj).apply(key);
} else if (obj instanceof FunctionBaseJsonNode) {
return ((FunctionBaseJsonNode) obj).get(key);
} else {
switch (key) {
case "$" + ExpressionHandlerUtils.SECRET_MAGIC:
return (Function<String, Object>) ExpressionHandlerUtils::getSecret;
return new PrefixJsonNode<>(ExpressionHandlerUtils::getOptionalSecret);
case "$" + ExpressionHandlerUtils.CONTEXT_MAGIC:
return ExpressionHandlerUtils.getContextFunction(context);
case "$" + ExpressionHandlerUtils.CONST_MAGIC:
Expand All @@ -53,6 +57,6 @@ public Object getMapValue(Object obj, String key) {

@Override
public boolean isMap(Object obj) {
return super.isMap(obj) || obj instanceof Function;
return super.isMap(obj) || obj instanceof Function || obj instanceof FunctionBaseJsonNode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,8 @@ private static Stream<Arguments> provideMagicWordExpressionsToTest() {
return Stream.of(
Arguments.of("$WORKFLOW.instanceId", "1111-2222-3333", getContext()),
Arguments.of("$SECRET.lettersonly", "secretlettersonly", getContext()),
Arguments.of("$SECRET.none", "null", getContext()),
// Arguments.of("$SECRET.dot.secret", "null", getContext()), // exception due to missing object at path .dot
Arguments.of("$SECRET.none", "", getContext()),
Arguments.of("$SECRET.dot.secret", "secretdotsecret", getContext()),
Arguments.of("$SECRET[\"dot.secret\"]", "secretdotsecret", getContext()),
Arguments.of("$SECRET[\"dash-secret\"]", "secretdashsecret", getContext()),
Arguments.of("$CONST.someconstant", "value", getContext()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;

import org.jbpm.ruleflow.core.Metadata;
Expand Down Expand Up @@ -53,8 +54,12 @@ public static JsonNode getConstants(KogitoProcessContext context) {
return node == null ? NullNode.instance : node;
}

public static Optional<String> getOptionalSecret(String key) {
return ConfigResolverHolder.getConfigResolver().getConfigProperty(key, String.class);
}

public static String getSecret(String key) {
return ConfigResolverHolder.getConfigResolver().getConfigProperty(key, String.class).orElse(null);
return getOptionalSecret(key).orElse(null);
}

public static Function<String, Object> getContextFunction(KogitoProcessContext context) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* 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.kie.kogito.jackson.utils;

import java.io.IOException;
import java.util.List;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonPointer;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.node.BaseJsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.MissingNode;

public class FunctionBaseJsonNode extends BaseJsonNode {

private static final long serialVersionUID = 1L;

@Override
public JsonToken asToken() {
return JsonToken.START_OBJECT;
}

@Override
public boolean isObject() {
return true;
}

@Override
public <T extends JsonNode> T deepCopy() {
return (T) this;
}

@Override
public JsonNode get(int index) {
return MissingNode.getInstance();
}

@Override
public JsonNode path(String fieldName) {
return get(fieldName);
}

@Override
public JsonNode path(int index) {
return MissingNode.getInstance();
}

@Override
protected JsonNode _at(JsonPointer ptr) {
return null;
}

@Override
public JsonNodeType getNodeType() {
return JsonNodeType.OBJECT;
}

@Override
public String asText() {
return null;
}

@Override
public JsonNode findValue(String fieldName) {
return get(fieldName);
}

@Override
public JsonNode findParent(String fieldName) {
return null;
}

@Override
public List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar) {
foundSoFar.add(findValue(fieldName));
return foundSoFar;
}

@Override
public List<String> findValuesAsText(String fieldName, List<String> foundSoFar) {
foundSoFar.add(findValue(fieldName).asText());
return foundSoFar;
}

@Override
public List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar) {
foundSoFar.add(findParent(fieldName));
return foundSoFar;
}

@Override
public boolean equals(Object o) {
return true;
}

@Override
public int hashCode() {
return 0;
}

@Override
public void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException {
// not serialize
}

@Override
public void serializeWithType(JsonGenerator jgen,
SerializerProvider provider,
TypeSerializer typeSer) throws IOException {
// not serialize
}

}
Loading

0 comments on commit dfbd63a

Please sign in to comment.