All Downloads are FREE. Search and download functionalities are using the official Maven repository.
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.sap.cds.impl.PreparedCqnStmt Maven / Gradle / Ivy
/************************************************************************
* © 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
************************************************************************/
package com.sap.cds.impl;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.Reader;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import com.sap.cds.CdsDataStoreException;
import com.sap.cds.CdsMissingValueException;
import com.sap.cds.impl.parser.token.Jsonizer;
import com.sap.cds.ql.CdsDataException;
import com.sap.cds.ql.cqn.CqnSelectListItem;
import com.sap.cds.ql.cqn.CqnStructuredTypeRef;
import com.sap.cds.ql.impl.ExpandProcessor;
import com.sap.cds.reflect.CdsBaseType;
import com.sap.cds.reflect.CdsEntity;
import com.sap.cds.reflect.CdsStructuredType;
import com.sap.cds.util.CdsTypeUtils;
public class PreparedCqnStmt implements PreparedCqnStatement {
private final CqnStructuredTypeRef ref;
private final CdsStructuredType targetType;
private final String nativeStatement;
private final List selectListItems;
private final List expands;
private final List excluding;
private final List params;
private PreparedCqnStmt(CqnStructuredTypeRef ref, CdsStructuredType targetType, String nativeStatement,
List selectListItems, List expands, List excluding, List parameters) {
this.ref = ref;
this.targetType = targetType;
this.nativeStatement = nativeStatement;
this.params = parameters;
this.selectListItems = selectListItems;
this.expands = expands;
this.excluding = excluding;
}
public static PreparedCqnStmt create(String nativeStatement, List selectListItems,
List expands, List excluding, List parameters, CqnStructuredTypeRef ref,
CdsStructuredType targetType) {
return new PreparedCqnStmt(ref, targetType, nativeStatement, selectListItems, expands, excluding, parameters);
}
public static PreparedCqnStmt createUpdate(String nativeStatement, List parameters,
CqnStructuredTypeRef ref, CdsEntity entity) {
return new PreparedCqnStmt(ref, entity, nativeStatement, emptyList(), emptyList(), emptyList(), parameters);
}
protected String toNative() {
return nativeStatement;
}
public List selectListItems() {
return unmodifiableList(selectListItems);
}
public List expands() {
return expands;
}
public List excluding() {
return unmodifiableList(excluding);
}
@SuppressWarnings("unchecked")
public T targetType() {
return (T) targetType;
}
public CqnStructuredTypeRef ref() {
return ref;
}
@Override
public String toString() {
return nativeStatement;
}
public abstract static class Parameter {
protected CdsBaseType type;
public abstract Object get(Map cqnParameters);
public abstract String name();
public Optional defaultValue() {
return Optional.empty();
}
public CdsBaseType type() {
return type;
}
@Override
public String toString() {
return name();
}
public Parameter type(Optional type) {
this.type = type.map(CdsBaseType::cdsType).orElse(null);
return this;
}
public Parameter type(CdsBaseType type) {
this.type = type;
return this;
}
}
public static class CqnParam extends Parameter {
final String name;
final Object defaultValue;
public CqnParam(String name) {
this(name, null);
}
public CqnParam(String name, Object defaultValue) {
this.name = name;
this.defaultValue = defaultValue;
}
@Override
public Object get(Map values) {
if (values.containsKey(name)) {
Object value = values.get(name);
if (type == CdsBaseType.UUID) {
value = CdsTypeUtils.parseUuid(value);
}
return value;
}
if (defaultValue != null) {
return defaultValue;
}
throw new CdsMissingValueException(name);
}
@Override
public String name() {
return name;
}
@Override
public Optional defaultValue() {
return Optional.ofNullable(defaultValue);
}
}
public static class DataParam extends Parameter {
private final String name;
private final String[] segs;
public DataParam(String name, CdsBaseType type) {
this.name = name;
this.type = type;
this.segs = name.split("\\.");
}
@Override
public Object get(Map values) {
if (values == null) {
return null;
}
Object result = values;
for (String seg : segs) {
result = asMap(result).get(seg);
if (result == null) {
return null;
}
}
return result;
}
@Override
public String name() {
return name;
}
}
public static class ValueParam extends Parameter {
final Supplier valueSupplier;
public ValueParam(Supplier valueSupplier) {
this.valueSupplier = valueSupplier;
}
@Override
public Object get(Map cqnParameters) {
return valueSupplier.get();
}
@Override
public String name() {
return valueSupplier != null ? valueSupplier.get().toString() : "null";
}
}
public static class JsonParam extends Parameter {
@Override
public Reader get(Map map) {
try {
PipedWriter writer = new PipedWriter();
PipedReader reader = new PipedReader(writer);
//TODO: we need to find a better solution here. Or at least clarify
//how CompletableFuture.runAsync() behaves in a Spring Boot context. Also,
//it would be desirable to only start the writer if a reader starts to read.
CompletableFuture.runAsync(() -> {
try {
Jsonizer.write(writer, map);
} catch (IOException e) {
throw new CdsDataException("Failed to serialize JSON data parameter: ", e);
}
});
return reader;
} catch (IOException e) {
throw new CdsDataStoreException("IO Exception during serialization of JSON content", e);
}
}
@Override
public CdsBaseType type() {
return CdsBaseType.LARGE_STRING;
}
@Override
public String name() {
return "$json";
}
}
public List parameters() {
return this.params;
}
@SuppressWarnings("unchecked")
private static Map asMap(Object result) {
try {
return (Map) result;
} catch (ClassCastException e) {
throw new CdsDataException("Data has unexpected type " + result.getClass().getName(), e);
}
}
}