package com.turkraft.springfilter.transformer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.Lists; import com.turkraft.springfilter.helper.FieldTypeResolver; import com.turkraft.springfilter.parser.node.FieldNode; import com.turkraft.springfilter.parser.node.FilterNode; import com.turkraft.springfilter.parser.node.InfixOperationNode; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; @Component @RequiredArgsConstructor public class TransformerUtils { private final FieldTypeResolver fieldTypeResolver; public JsonNode wrapArrays(FilterJsonNodeTransformer transformer, JsonNode node, InfixOperationNode source) { if (!(source.getLeft() instanceof FieldNode)) { return node; } String textValue = transformer.transform(source.getLeft()).textValue(); String[] fields = textValue.replace("$", "").split("\\."); List arrayPaths = new ArrayList<>(); String fullPath = ""; String prevArrayPath = ""; for (String field : fields) { if (fullPath.isEmpty()) { fullPath = fullPath.concat(field); } else { fullPath = fullPath.concat(".").concat(field); } Boolean isArray = fieldTypeResolver.resolve(transformer.getEntityType(), fullPath.replace("_id", "id")).getIsArray(); if (isArray) { String result = fullPath.replace(prevArrayPath, ""); if (!arrayPaths.isEmpty()) result = result.replaceFirst("\\.", ""); arrayPaths.add(result); prevArrayPath = fullPath; } } if (arrayPaths.isEmpty()) { return node; } JsonNode resultNode = null; for (int i = arrayPaths.size() - 1; i >= 0; i--) { String input = (i > 0) ? "$$this.".concat(arrayPaths.get(i)) : "$".concat(arrayPaths.get(i)); if (resultNode == null) { List split = Lists.newArrayList(transformer.transform(source.getLeft()).asText() .split(arrayPaths.get(i), 2)); if (split.size() == 1) { split.add(""); } String nodeName = "$this".concat(split.get(1)); FilterNode left = new FieldNode(nodeName, source.getLeft().getPayload()); left.setPayload(source.getLeft().getPayload()); JsonNode newNode = transformer.getObjectMapper().createObjectNode().set("$and", transformer.getObjectMapper().createArrayNode() .add(transformer.getObjectMapper().createObjectNode() .set("$isArray", transformer.getObjectMapper().createArrayNode() .add(transformer.transform(source.getRight())))) .add(transformer.getObjectMapper().createObjectNode().set("$in", transformer.getObjectMapper().createArrayNode() .add(transformer.transform(left)) .add(transformer.transform(source.getRight()))))); JsonNode ifNull = transformer.getObjectMapper().createObjectNode().set("$ifNull", transformer.getObjectMapper().createArrayNode().add(input).add(transformer.getObjectMapper().createArrayNode())); resultNode = transformer.getObjectMapper().createObjectNode().set("$anyElementTrue", transformer.getObjectMapper().createObjectNode().set("$map", transformer.getObjectMapper().createObjectNode() .putPOJO("input", ifNull) .set("in", newNode))); } else { JsonNode ifNull = transformer.getObjectMapper().createObjectNode().set("$ifNull", transformer.getObjectMapper().createArrayNode().add(input).add(transformer.getObjectMapper().createArrayNode())); resultNode = transformer.getObjectMapper().createObjectNode().set("$anyElementTrue", transformer.getObjectMapper().createObjectNode().set("$map", transformer.getObjectMapper().createObjectNode() .putPOJO("input", ifNull) .set("in", resultNode))); } } return resultNode; } public JsonNode wrapArraysRegex(FilterJsonNodeTransformer transformer, JsonNode node, InfixOperationNode source) { if (!(source.getLeft() instanceof FieldNode)) { return node; } String textValue = transformer.transform(source.getLeft()).textValue(); String[] fields = textValue.replace("$", "").split("\\."); List arrayPaths = new ArrayList<>(); String fullPath = ""; String prevArrayPath = ""; for (String field : fields) { if (fullPath.isEmpty()) { fullPath = fullPath.concat(field); } else { fullPath = fullPath.concat(".").concat(field); } Boolean isArray = fieldTypeResolver.resolve(transformer.getEntityType(), fullPath.replace("_id", "id")).getIsArray(); if (isArray) { String result = fullPath.replace(prevArrayPath, ""); if (!arrayPaths.isEmpty()) result = result.replaceFirst("\\.", ""); arrayPaths.add(result); prevArrayPath = fullPath; } } if (arrayPaths.isEmpty()) { return node; } JsonNode resultNode = null; for (int i = arrayPaths.size() - 1; i >= 0; i--) { String input = (i > 0) ? "$$this.".concat(arrayPaths.get(i)) : "$".concat(arrayPaths.get(i)); if (resultNode == null) { List split = Lists.newArrayList(transformer.transform(source.getLeft()).asText() .split(arrayPaths.get(i), 2)); if (split.size() == 1) { split.add(""); } JsonNode regex = node.findValue("$regexMatch"); ObjectNode regexPayload = (ObjectNode) regex; regexPayload.put("input", "$$this"); JsonNode ifNull = transformer.getObjectMapper().createObjectNode().set("$ifNull", transformer.getObjectMapper().createArrayNode().add(input).add(transformer.getObjectMapper().createArrayNode())); resultNode = transformer.getObjectMapper().createObjectNode().set("$anyElementTrue", transformer.getObjectMapper().createObjectNode().set("$map", transformer.getObjectMapper().createObjectNode() .putPOJO("input", ifNull) .set("in", node))); } else { JsonNode ifNull = transformer.getObjectMapper().createObjectNode().set("$ifNull", transformer.getObjectMapper().createArrayNode().add(input).add(transformer.getObjectMapper().createArrayNode())); resultNode = transformer.getObjectMapper().createObjectNode().set("$anyElementTrue", transformer.getObjectMapper().createObjectNode().set("$map", transformer.getObjectMapper().createObjectNode() .putPOJO("input", ifNull) .set("in", resultNode))); } } return resultNode; } public JsonNode wrapArrays(FilterJsonNodeTransformer transformer, JsonNode node, InfixOperationNode source, String mongoOperator) { if (!(source.getLeft() instanceof FieldNode)) { return node; } String textValue = transformer.transform(source.getLeft()).textValue(); String[] fields = textValue.replace("$", "").split("\\."); List arrayPaths = new ArrayList<>(); String fullPath = ""; String prevArrayPath = ""; for (String field : fields) { if (fullPath.isEmpty()) { fullPath = fullPath.concat(field); } else { fullPath = fullPath.concat(".").concat(field); } Boolean isArray = fieldTypeResolver.resolve(transformer.getEntityType(), fullPath.replace("_id", "id")).getIsArray(); if (isArray) { String result = fullPath.replace(prevArrayPath, ""); if (!arrayPaths.isEmpty()) result = result.replaceFirst("\\.", ""); arrayPaths.add(result); prevArrayPath = fullPath; } } if (arrayPaths.isEmpty()) { return node; } JsonNode resultNode = null; for (int i = arrayPaths.size() - 1; i >= 0; i--) { String input = (i > 0) ? "$$this.".concat(arrayPaths.get(i)) : "$".concat(arrayPaths.get(i)); if (resultNode == null) { List split = Lists.newArrayList(transformer.transform(source.getLeft()).asText() .split(arrayPaths.get(i), 2)); if (split.size() == 1) { split.add(""); } String nodeName = "$this".concat(split.get(1)); FilterNode left = new FieldNode(nodeName, source.getLeft().getPayload()); left.setPayload(source.getLeft().getPayload()); JsonNode newNode = transformer.getObjectMapper().createObjectNode().set(mongoOperator, transformer.getObjectMapper().createArrayNode() .add(transformer.transform(left)) .add(transformer.transform(source.getRight()))); JsonNode ifNull = transformer.getObjectMapper().createObjectNode().set("$ifNull", transformer.getObjectMapper().createArrayNode().add(input).add(transformer.getObjectMapper().createArrayNode())); resultNode = transformer.getObjectMapper().createObjectNode().set("$anyElementTrue", transformer.getObjectMapper().createObjectNode().set("$map", transformer.getObjectMapper().createObjectNode() .putPOJO("input", ifNull) .set("in", newNode))); } else { JsonNode ifNull = transformer.getObjectMapper().createObjectNode().set("$ifNull", transformer.getObjectMapper().createArrayNode().add(input).add(transformer.getObjectMapper().createArrayNode())); resultNode = transformer.getObjectMapper().createObjectNode().set("$anyElementTrue", transformer.getObjectMapper().createObjectNode().set("$map", transformer.getObjectMapper().createObjectNode() .putPOJO("input", ifNull) .set("in", resultNode))); } } return resultNode; } }