com.sap.cds.util.CdsModelUtils Maven / Gradle / Ivy
/*******************************************************************
* © 2020 SAP SE or an SAP affiliate company. All rights reserved. *
*******************************************************************/
package com.sap.cds.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.sap.cds.CdsException;
import com.sap.cds.impl.parser.VersionParser;
import com.sap.cds.ql.cqn.CqnElementRef;
import com.sap.cds.ql.cqn.CqnPredicate;
import com.sap.cds.ql.cqn.CqnReference.Segment;
import com.sap.cds.ql.cqn.CqnStructuredTypeRef;
import com.sap.cds.ql.cqn.CqnVisitor;
import com.sap.cds.reflect.CdsAssociationType;
import com.sap.cds.reflect.CdsElement;
import com.sap.cds.reflect.CdsEntity;
import com.sap.cds.reflect.CdsModel;
import com.sap.cds.reflect.CdsStructuredType;
import com.sap.cds.reflect.CdsType;
import com.sap.cds.reflect.impl.CdsVersion;
import com.sap.cds.reflect.impl.DraftAdapter;
import com.sap.cds.reflect.impl.reader.model.CdsConstants;
public class CdsModelUtils {
private static final CdsVersion DEFAULT_COMPILER_VERSION = new CdsVersion(1, 0, 0, 0);
private CdsModelUtils() {
}
public static boolean isSingleValued(CdsType associationElement) {
return associationElement.as(CdsAssociationType.class).getCardinality().getTargetMax().equals("1");
}
public static Set targetKeys(CdsElement association) {
CdsEntity target = association.getType().as(CdsAssociationType.class).getTarget();
return resolveKeys(target).collect(Collectors.toSet());
}
public static Set keyNames(CdsStructuredType entity) {
return resolveKeys(entity).collect(Collectors.toSet());
}
private static Stream resolveKeys(CdsStructuredType entity) {
return entity.keyElements().filter(k -> !k.isVirtual()).flatMap(CdsModelUtils::resolveKeys);
}
private static Stream resolveKeys(CdsElement element) {
if (element.getType().isAssociation()) {
return resolveKeys(element.getType().as(CdsAssociationType.class).getTarget())
.map(k -> element.getName() + "_" + k);
}
return Stream.of(element.getName());
}
public static Optional findElement(CdsStructuredType root, CqnElementRef ref) {
try {
return Optional.of(element(root, ref));
} catch (CdsException e) {
return Optional.empty();
}
}
public static CdsElement element(CdsStructuredType root, CqnElementRef ref) {
return element(root, ref.segments());
}
public static CdsElement element(CdsStructuredType root, List extends Segment> segments) {
CdsStructuredType type = root;
Iterator extends Segment> iter = segments.iterator();
boolean firstSegment = true;
while (iter.hasNext()) {
Segment segment = iter.next();
if (firstSegment && (segment.id().equals(root.getQualifiedName()))) {
firstSegment = false;
continue;
}
if (iter.hasNext()) {
CdsElement element = type.getElement(segment.id());
CdsType elementType = element.getType();
if (elementType.isAssociation()) {
type = elementType.as(CdsAssociationType.class).getTarget();
} else if (elementType.isStructured()) {
type = elementType.as(CdsStructuredType.class);
}
firstSegment = false;
} else {
return type.getElement(segment.id());
}
}
throw new CdsException("Cannot find element " + segments + " of entity " + root);
}
public static boolean isContextElementRef(CqnElementRef ref) {
switch (ref.firstSegment()) {
case "$now":
case "$at":
case "$user":
return true;
default:
return false;
}
}
public static List entities(CdsModel model, List extends Segment> segments) {
List entities = new ArrayList<>(segments.size());
Iterator extends Segment> iter = segments.iterator();
if (iter.hasNext()) {
CdsEntity e = model.getEntity(iter.next().id());
entities.add(e);
while (iter.hasNext()) {
e = e.getTargetOf(iter.next().id());
entities.add(e);
}
}
return entities;
}
public static List entities(CdsEntity root, List extends Segment> segments) {
LinkedList entities = new LinkedList<>();
entities.add(root);
boolean firstSegment = true;
for (Segment seg : segments) {
if (firstSegment && root.getQualifiedName().equals(seg.id())) {
continue;
}
entities.add(entities.getLast().getTargetOf(seg.id()));
firstSegment = false;
}
return entities;
}
public static CdsEntity entity(CdsEntity root, List extends Segment> segments) {
return ((LinkedList) entities(root, segments)).getLast();
}
public static CdsStructuredType target(CdsStructuredType root, List extends Segment> segments) {
CdsStructuredType target = root;
for (Segment seg : segments) {
target = target.getTargetOf(seg.id());
}
return target;
}
public static CdsEntity entity(CdsModel model, List extends Segment> segments) {
CdsEntity entity = model.getEntity(segments.get(0).id());
return entity(entity, segments);
}
public static CdsEntity entity(CdsModel model, CqnStructuredTypeRef ref) {
CdsEntity entity = model.getEntity(ref.firstSegment());
return entity(entity, ref.segments());
}
public static boolean isReverseAssociation(CdsElement assoc) {
CdsAssociationType association = assoc.getType();
if (association.getCardinality().getTargetMax().equalsIgnoreCase("*")) {
return true;
}
return referencesAllKeysOfSource(assoc);
}
public static CdsVersion compilerVersion(CdsModel model) {
String creator = model.getMeta(CdsConstants.CREATOR);
if (creator == null) {
return DEFAULT_COMPILER_VERSION;
}
try {
return VersionParser.parse(creator.substring("CDS Compiler v".length()));
} catch (IllegalArgumentException e) {
return DEFAULT_COMPILER_VERSION;
}
}
private static boolean referencesAllKeysOfSource(CdsElement assoc) {
CdsAssociationType association = assoc.getType();
Optional onCond = association.onCondition();
if (!onCond.isPresent()) {
return false;
}
Set sourceKeys = keyNames(assoc.getDeclaringType());
sourceKeys.remove(DraftAdapter.IS_ACTIVE_ENTITY); // TODO CDSJAVA-2385
CqnVisitor visitor = new CqnVisitor() {
@Override
public void visit(CqnElementRef ref) {
if (ref.lastSegment().equals("$self")) {
sourceKeys.clear();
} else if (ref.segments().size() == 1) {
sourceKeys.remove(ref.lastSegment());
}
}
};
onCond.get().accept(visitor);
return sourceKeys.isEmpty();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy