com.sap.cds.jdbc.hana.hierarchies.HierarchySubsetBuilder 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.Optional;
import com.sap.cds.impl.parser.token.CqnBoolLiteral;
import com.sap.cds.impl.parser.token.Jsonizer;
import com.sap.cds.ql.Source;
import com.sap.cds.ql.StructuredType;
import com.sap.cds.ql.TableFunction;
import com.sap.cds.ql.cqn.CqnPredicate;
import com.sap.cds.ql.cqn.CqnSource;
import com.sap.cds.ql.cqn.CqnVisitor;
import com.sap.cds.ql.hana.HierarchySubset;
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 HierarchySubsetBuilder implements HierarchySubset {
private static final CdsType INTEGER = CdsSimpleTypeBuilder.simpleType(CdsBaseType.INT32);
private static final CdsElementDefinition DISTANCE = element("hierarchy_distance").type(INTEGER).isNotNull(true)
.build();
private final boolean isAncestors;
protected final Source> source;
protected CqnPredicate startWhere;
// distance
private int from = 0;
private int to = 0;
private HierarchySubsetBuilder(Source> source, boolean isAncestors) {
this.source = source;
this.isAncestors = isAncestors;
if (isAncestors) {
this.from = Integer.MIN_VALUE;
} else {
this.to = Integer.MAX_VALUE;
}
}
public static HierarchySubsetBuilder ancestors(Source> source) {
return new HierarchySubsetBuilder(source, true);
}
public static HierarchySubsetBuilder descendants(Source> source) {
return new HierarchySubsetBuilder(source, false);
}
@Override
public TableFunction copy(Source> source) {
HierarchySubsetBuilder impl = new HierarchySubsetBuilder(source, isAncestors);
impl.startWhere = startWhere;
impl.from = from;
impl.to = to;
return impl;
}
@Override
public HierarchySubsetBuilder startWhere(CqnPredicate startWhere) {
this.startWhere = startWhere == CqnBoolLiteral.TRUE ? null : startWhere;
return this;
}
@Override
public Optional startWhere() {
return Optional.ofNullable(startWhere);
}
@Override
public int from() {
return from;
}
@Override
public int to() {
return to;
}
@Override
public HierarchySubsetBuilder from(int from) {
this.from = from;
return this;
}
@Override
public HierarchySubsetBuilder to(int to) {
this.to = to;
return this;
}
@Override
public HierarchySubsetBuilder distance(int from, int to) {
this.from = from;
this.to = to;
return this;
}
@Override
public HierarchySubsetBuilder distance(int distanceFromStart, boolean keepStart) {
if (isAncestors) {
return distance(distanceFromStart < 0 ? Integer.MIN_VALUE : -distanceFromStart, keepStart ? 0 : -1);
}
return distance(keepStart ? 0 : 1, distanceFromStart < 0 ? Integer.MAX_VALUE : distanceFromStart);
}
@Override
public CqnSource source() {
return source;
}
@Override
public StructuredType> getType() {
return source.getType();
}
@Override
public void accept(CqnVisitor visitor) {
}
@Override
public String toJson() {
Jsonizer cqn = Jsonizer.object("source", source);
if (startWhere != null) {
cqn.put("startWhere", startWhere);
}
if (from > Integer.MIN_VALUE && from < Integer.MAX_VALUE) {
cqn.put("from", from);
}
if (to > Integer.MIN_VALUE && to < Integer.MAX_VALUE) {
cqn.put("to", to);
}
String subset = isAncestors ? "ancestors" : "descendants";
return Jsonizer.object(subset, cqn).toJson();
}
@Override
public boolean isAncestors() {
return isAncestors;
}
@Override
public boolean isDescendants() {
return !isAncestors;
}
@Override
public CdsStructuredType rowType(CdsStructuredType sourceRowType) {
return CqnStatementUtils.addElementsTo(sourceRowType, DISTANCE);
}
@Override
public String name() {
return isAncestors ? "HIERARCHY_ANCESTORS" : "HIERARCHY_DESCENDANTS";
}
}