Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.exactpro.sf.services.json.JSONVisitorEncode Maven / Gradle / Ivy
/******************************************************************************
* Copyright 2009-2023 Exactpro (Exactpro Systems Limited)
*
* Licensed 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 com.exactpro.sf.services.json;
import static com.exactpro.sf.extensions.IMessageExtensionsKt.isFieldPresent;
import static com.fasterxml.jackson.databind.node.JsonNodeFactory.instance;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.BooleanNode;
import com.fasterxml.jackson.databind.node.DecimalNode;
import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.LongNode;
import com.fasterxml.jackson.databind.node.NullNode;
import com.fasterxml.jackson.databind.node.TextNode;
import org.apache.commons.lang3.BooleanUtils;
import com.exactpro.sf.common.messages.DefaultMessageStructureVisitor;
import com.exactpro.sf.common.messages.IMessage;
import com.exactpro.sf.common.messages.MessageStructureReader;
import com.exactpro.sf.common.messages.MessageStructureReaderHandlerImpl;
import com.exactpro.sf.common.messages.structures.IDictionaryStructure;
import com.exactpro.sf.common.messages.structures.IFieldStructure;
import com.exactpro.sf.common.messages.structures.IMessageStructure;
import com.exactpro.sf.common.messages.structures.StructureUtils;
import com.exactpro.sf.comparison.conversion.MultiConverter;
import com.fasterxml.jackson.databind.JsonNode;
public class JSONVisitorEncode extends DefaultMessageStructureVisitor {
protected IJsonNodeWrapper root;
protected final IDictionaryStructure dictionary;
protected final Supplier structureReaderSupplier;
private final IMessage message;
private final Map dynamicStructures;
private final JsonSettings jsonSettings;
public JSONVisitorEncode(IJsonNodeWrapper root, IDictionaryStructure dictionary, IMessage message) {
this(root, dictionary, Collections.emptyMap(), message);
}
public JSONVisitorEncode(IJsonNodeWrapper root, IDictionaryStructure dictionary, Map dynamicStructures, IMessage message) {
this(root, dictionary, dynamicStructures, new JsonSettings(), message);
}
public JSONVisitorEncode(IJsonNodeWrapper root, IDictionaryStructure dictionary, Map dynamicStructures, JsonSettings jsonSettings, IMessage message) {
this(root, dictionary, () -> MessageStructureReader.READER, dynamicStructures, jsonSettings, message);
}
public JSONVisitorEncode(IJsonNodeWrapper root, IDictionaryStructure dictionary, Supplier structureReaderSupplier, Map dynamicStructures, JsonSettings jsonSettings, IMessage message) {
this.root = root;
this.dictionary = dictionary;
this.structureReaderSupplier = structureReaderSupplier;
this.dynamicStructures = dynamicStructures;
this.jsonSettings = jsonSettings;
this.message = message;
}
public JSONVisitorEncode(IJsonNodeWrapper root, IDictionaryStructure dictionary, Supplier structureReaderSupplier, Map dynamicStructures, IMessage message) {
this(root,dictionary,structureReaderSupplier, dynamicStructures, new JsonSettings(), message);
}
@Override
public void visit(String fieldName, String value, IFieldStructure fldStruct, boolean isDefault) {
visitSimple(value, fldStruct, TextNode::new);
}
@Override
public void visit(String fieldName, Character value, IFieldStructure fldStruct, boolean isDefault) {
visitSimple(value, fldStruct, JSONVisitorUtility::convertCharToTextNode);
}
@Override
public void visit(String fieldName, BigDecimal value, IFieldStructure fldStruct, boolean isDefault) {
visitSimple(value, fldStruct, DecimalNode::new);
}
@Override
public void visit(String fieldName, Long value, IFieldStructure fldStruct, boolean isDefault) {
visitSimple(value, fldStruct, LongNode::new);
}
@Override
public void visit(String fieldName, Integer value, IFieldStructure fldStruct, boolean isDefault) {
visitSimple(value, fldStruct, IntNode::new);
}
@Override
public void visit(String fieldName, Byte value, IFieldStructure fldStruct, boolean isDefault) {
visitSimple(value, fldStruct, (Function)IntNode::new);
}
@Override
public void visit(String fieldName, Boolean value, IFieldStructure fldStruct, boolean isDefault) {
visitSimple(value, fldStruct, BooleanNode::valueOf);
}
@Override
public void visit(String fieldName, IMessage message, IFieldStructure fldStruct, boolean isDefault) {
visitSimple(message, fldStruct, msg -> writeMessage(msg, (IMessageStructure)fldStruct));
}
@Override
public void visitMessageCollection(String fieldName, List message, IFieldStructure fldStruct, boolean isDefault) {
visitList(message, fldStruct, msg -> writeMessageList(msg, (IMessageStructure)fldStruct));
}
@Override
public void visitStringCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
visitList(value, fldStruct, TextNode::new);
}
@Override
public void visitCharCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
visitList(value, fldStruct, JSONVisitorUtility::convertCharToTextNode);
}
@Override
public void visitLongCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
visitList(value, fldStruct, LongNode::new);
}
@Override
public void visitIntCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
visitList(value, fldStruct, IntNode::new);
}
@Override
public void visitBigDecimalCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
visitList(value, fldStruct, DecimalNode::new);
}
@Override
public void visitBooleanCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
visitList(value, fldStruct, BooleanNode::valueOf);
}
@Override
public void visit(String fieldName, LocalDateTime value, IFieldStructure fldStruct, boolean isDefault) {
String formatted = null;
if(value != null) formatted = JSONVisitorUtility.FORMATTER.format(value);
visitSimple(formatted, fldStruct, TextNode::new);
}
protected void visitSimple(T value, IFieldStructure fldStruct, Function converter) {
if (!isWriteable(value, fldStruct)) {
return;
}
String jsonFieldName = JSONVisitorUtility.getJsonFieldName(fldStruct);
if(value == null && isFieldPresent(message, fldStruct.getName())) {
if(root.isArray()) {
root.add(NullNode.instance);
} else {
root.set(jsonFieldName, NullNode.instance);
}
return;
}
JsonNode node = jsonSettings.isTreatSimpleValuesAsStrings() && !(value instanceof IMessage) ? new TextNode(MultiConverter.convert(value, String.class)) : converter.apply(value);
if (root.isArray()) {
root.add(node);
} else {
root.set(jsonFieldName, node);
}
}
protected void visitList(List value, IFieldStructure fldStruct, Function converter) {
if (!isWriteable(value, fldStruct)) {
return;
}
String jsonFieldName = JSONVisitorUtility.getJsonFieldName(fldStruct);
boolean isNoName = BooleanUtils.toBoolean(StructureUtils.getAttributeValue(fldStruct, JSONMessageHelper.IS_NO_NAME_ATTR));
if(value == null && isFieldPresent(message, fldStruct.getName())) {
if(isNoName) return;
if(root.isArray()) {
root.add(NullNode.instance);
} else {
root.set(jsonFieldName, NullNode.instance);
}
return;
}
ArrayNode array = instance.arrayNode(value.size());
for (T item : value) {
if(item == null) {
array.add(NullNode.instance);
continue;
}
array.add(jsonSettings.isTreatSimpleValuesAsStrings() && !(item instanceof IMessage) ? new TextNode(item.toString()) : converter.apply(item));
}
if (isNoName) {
root = new ArrayNodeWrapper(array);
} else if (root.isArray()) {
root.add(array);
} else {
root.set(jsonFieldName, array);
}
}
protected JsonNode writeMessageList(IMessage message, IMessageStructure structure) {
IMessageStructure messageStructure = dictionary.getMessages().getOrDefault(structure.getReferenceName(), (IMessageStructure)dynamicStructures.get(structure.getReferenceName()));
boolean isObject = !BooleanUtils.toBoolean(StructureUtils.getAttributeValue(messageStructure, JSONMessageHelper.IS_NO_OBJECT_ATTR));
boolean fromArray = BooleanUtils.toBoolean(StructureUtils.getAttributeValue(structure, JSONMessageHelper.FROM_ARRAY_ATTR));
IJsonNodeWrapper node = null;
if (fromArray) {
node = new ArrayNodeWrapper(instance.arrayNode(messageStructure.getFields().size()));
} else if (isObject) {
node = new ObjectNodeWrapper(instance.objectNode());
}
JSONVisitorEncode visitor = createVisitor(node, message);
MessageStructureReader structureReader = structureReaderSupplier.get();
structureReader.traverse(visitor, messageStructure, message, MessageStructureReaderHandlerImpl.instance());
return visitor.getRoot();
}
protected JsonNode writeMessage(IMessage message, IMessageStructure messageStructure) {
boolean isObject = !BooleanUtils.toBoolean(StructureUtils.getAttributeValue(messageStructure, JSONMessageHelper.IS_NO_NAME_ATTR));
boolean fromArray = BooleanUtils.toBoolean(StructureUtils.getAttributeValue(messageStructure, JSONMessageHelper.FROM_ARRAY_ATTR));
IJsonNodeWrapper node = null;
if (fromArray) {
node = new ArrayNodeWrapper(instance.arrayNode(messageStructure.getFields().size()));
} else if (isObject) {
node = new ObjectNodeWrapper(instance.objectNode());
}
JSONVisitorEncode visitor = createVisitor(node, message);
MessageStructureReader structureReader = structureReaderSupplier.get();
structureReader.traverse(visitor, messageStructure, message, MessageStructureReaderHandlerImpl.instance());
return visitor.getRoot();
}
protected JSONVisitorEncode createVisitor(IJsonNodeWrapper root, IMessage message) {
return new JSONVisitorEncode(root, dictionary, dynamicStructures, jsonSettings, message);
}
protected boolean isWriteable(Object value, IFieldStructure fldStruct) {
return (value != null || isFieldPresent(message, fldStruct.getName())) && JSONVisitorUtility.isWritable(fldStruct);
}
public JsonNode getRoot() {
return root.getNode();
}
}