com.sap.cds.jdbc.hana.hierarchies.HierarchyGeneratorBuilder Maven / Gradle / Ivy
/*******************************************************************
* © 2024 SAP SE or an SAP affiliate company. All rights reserved. *
*******************************************************************/
package com.sap.cds.jdbc.hana.hierarchies;
import static com.sap.cds.reflect.impl.CdsElementBuilder.element;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import com.sap.cds.impl.parser.token.Jsonizer;
import com.sap.cds.ql.CQL;
import com.sap.cds.ql.Source;
import com.sap.cds.ql.StructuredType;
import com.sap.cds.ql.cqn.CqnPredicate;
import com.sap.cds.ql.cqn.CqnSelect;
import com.sap.cds.ql.cqn.CqnSortSpecification;
import com.sap.cds.ql.cqn.CqnSource;
import com.sap.cds.ql.cqn.CqnVisitor;
import com.sap.cds.ql.hana.CqnHierarchyGenerator;
import com.sap.cds.ql.hana.Hierarchy;
import com.sap.cds.reflect.CdsBaseType;
import com.sap.cds.reflect.CdsElementDefinition;
import com.sap.cds.reflect.CdsStructuredType;
import com.sap.cds.reflect.CdsType;
import com.sap.cds.reflect.impl.CdsSimpleTypeBuilder;
import com.sap.cds.util.CqnStatementUtils;
public class HierarchyGeneratorBuilder implements CqnHierarchyGenerator, Hierarchy {
private static final CdsType BIGINT = CdsSimpleTypeBuilder.simpleType(CdsBaseType.INT64);
private static final CdsType INTEGER = CdsSimpleTypeBuilder.simpleType(CdsBaseType.INT32);
private static final CdsElementDefinition RANK = element("hierarchy_rank").type(BIGINT).isNotNull(true).build();
private static final CdsElementDefinition LEVEL = element("hierarchy_level").type(INTEGER).isNotNull(true).build();
private static final CdsElementDefinition TREE_SIZE = element("hierarchy_tree_size").type(BIGINT).isNotNull(true)
.build();
private final List siblingOrderBy;
private final Source> source;
private Integer depth;
private CqnPredicate startWhere;
private HierarchyGeneratorBuilder(Source> source) {
this.source = source;
this.siblingOrderBy = new ArrayList<>();
}
public static HierarchyGeneratorBuilder create(Source> source) {
return new HierarchyGeneratorBuilder(source);
}
public static HierarchyGeneratorBuilder create(CqnSelect source) {
return new HierarchyGeneratorBuilder((Source>) source);
}
@Override
public void accept(CqnVisitor visitor) {
}
@Override
public String toJson() {
Jsonizer cqn = Jsonizer.object("source", source);
if (depth != null) {
cqn.put("depth", depth);
}
if (startWhere != null) {
cqn.put("startWhere", startWhere);
}
if (!siblingOrderBy.isEmpty()) {
cqn.put("siblingOrderBy", siblingOrderBy);
}
return Jsonizer.object("hierarchy", cqn).toJson();
}
@Override
public StructuredType> getType() {
// TODO add hierarchy elements ?
return source.getType();
}
@Override
public CqnSource source() {
return source;
}
@Override
public List orderBy() {
return siblingOrderBy;
}
@Override
public Integer depth() {
return depth;
}
@Override
public Optional startWhere() {
return Optional.ofNullable(startWhere);
}
@Override
public HierarchyGeneratorBuilder orderBy(CqnSortSpecification... siblingOrderBy) {
return orderBy(List.of(siblingOrderBy));
}
@Override
public HierarchyGeneratorBuilder orderBy(List siblingOrderBy) {
this.siblingOrderBy.clear();
this.siblingOrderBy.addAll(siblingOrderBy);
return this;
}
@Override
public HierarchyGeneratorBuilder orderBy(String... siblingOrderBy) {
this.siblingOrderBy.clear();
this.siblingOrderBy.addAll(Arrays.stream(siblingOrderBy).map(o -> CQL.get(o).asc()).toList());
return this;
}
/**
* Restrict the depth of the hierarchy
*
* @param depth the depth; a depth of 0 selects root nodes only
* @return this HierarchyImpl
*/
@Override
public HierarchyGeneratorBuilder depth(Integer depth) {
this.depth = depth;
return this;
}
@Override
public HierarchyGeneratorBuilder startWhere(CqnPredicate startWhere) {
this.startWhere = startWhere;
return this;
}
@Override
public HierarchyGeneratorBuilder copy(Source> source) {
return create(source).depth(depth).orderBy(siblingOrderBy).startWhere(startWhere);
}
@Override
public CdsStructuredType rowType(CdsStructuredType sourceRowType) {
return CqnStatementUtils.addElementsTo(sourceRowType, RANK, LEVEL, TREE_SIZE);
}
@Override
public String name() {
return "HIERARCHY";
}
}