
com.sap.cds.reflect.impl.CdsAssociationReader Maven / Gradle / Ivy
/*******************************************************************
* © 2020 SAP SE or an SAP affiliate company. All rights reserved. *
*******************************************************************/
package com.sap.cds.reflect.impl;
import static com.sap.cds.impl.parser.TokenParser.elementRef;
import static com.sap.cds.reflect.impl.CdsAnnotationReader.isAnnotation;
import static com.sap.cds.reflect.impl.CdsAssociationTypeBuilder.managed;
import static com.sap.cds.reflect.impl.CdsAssociationTypeBuilder.unmanaged;
import static com.sap.cds.reflect.impl.CdsModelReader.readType;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.sap.cds.impl.parser.ExpressionParser;
import com.sap.cds.ql.cqn.CqnElementRef;
import com.sap.cds.ql.cqn.CqnPredicate;
import com.sap.cds.reflect.CdsAssociationType;
import com.sap.cds.reflect.CdsAssociationType.Cardinality;
import com.sap.cds.reflect.impl.reader.issuecollector.IssueCollector;
import com.sap.cds.reflect.impl.reader.issuecollector.IssueCollectorFactory;
import com.sap.cds.reflect.impl.reader.model.CdsConstants;
import com.sap.cds.util.StructuredTypeResolver;
public class CdsAssociationReader {
private static final IssueCollector issueCollector = IssueCollectorFactory
.getIssueCollector(CdsAssociationReader.class);
private final CdsModelBuilder model;
private final StructuredTypeResolver structResolver;
private final CdsModelReader.Config config;
public CdsAssociationReader(CdsModelReader.Config config, CdsModelBuilder model, StructuredTypeResolver structResolver) {
this.config = config;
this.model = model;
this.structResolver = structResolver;
}
public CdsTypeBuilder extends CdsAssociationType> read(String path, JsonNode csn) {
Iterator> fields = csn.fields();
boolean isComposition = false;
CdsEntityBuilder target = null;
CdsTypeBuilder> targetAspect = null;
CqnPredicate on = null;
Cardinality cardinality = null;
Set keyElements = new LinkedHashSet<>();
String doc = null;
while (fields.hasNext()) {
String elementName = fields.next().getKey();
if (!isAnnotation(elementName)) {
JsonNode elementValue = csn.get(elementName);
switch (elementName) {
case CdsConstants.TYPE:
isComposition = elementValue.asText().equals(CdsConstants.COMPOSITION);
break;
case CdsConstants.TARGET:
target = model.getEntity(elementValue.asText());
break;
case CdsConstants.TARGET_ASPECT:
if (elementValue.has(CdsConstants.ELEMENTS)) {
targetAspect = readTargetAspect(path, elementValue);
} else {
targetAspect = model.getAspect(elementValue.asText());
}
break;
case CdsConstants.CARDINALITY:
cardinality = readCardinality(path, csn.get(elementName), isComposition);
break;
case CdsConstants.ON:
on = ExpressionParser.parsePredicate(elementValue.toString());
break;
case CdsConstants.KIND:
case CdsConstants.KEYS:
for (JsonNode n : elementValue) {
CqnElementRef ref = elementRef(n);
keyElements.add(ref);
if (ref.size() > 1) {
issueCollector.unsupported(path, "The association '%s' has a path as key '%s'.", path, ref);
}
}
break;
case CdsConstants.DOC:
if (config.readDocs()) {
doc = csn.get(elementName).asText();
}
break;
case CdsConstants.KEY:
case CdsConstants.NOT_NULL:
break;
default:
issueCollector.unrecognized(path, "The association '%s' contains an unrecognized property '%s'.",
path, elementName);
}
}
}
if (cardinality == null) {
String srcMax = isComposition ? "1" : "*";
cardinality = CdsAssociationTypeBuilder.CardinalityImpl.create(srcMax, "0", "1");
}
if (on != null) {
return unmanaged(CdsAnnotationReader.read(config, csn), target, cardinality, isComposition, on, targetAspect, doc);
}
return managed(CdsAnnotationReader.read(config, csn), target, keyElements, cardinality, isComposition, targetAspect, doc);
}
private CdsTypeBuilder> readTargetAspect(String typeName, JsonNode elementValue) {
ObjectNode modifiedJsonNode = ((ObjectNode) elementValue).put(CdsConstants.KIND, CdsConstants.ASPECT);
return readType(config, typeName, new ObjectMapper().convertValue(modifiedJsonNode, JsonNode.class), model,
structResolver);
}
private static Cardinality readCardinality(String path, JsonNode csn, boolean isComposition) {
String sourceMax = null;
String targetMin = "0";
String targetMax = "1";
Iterator> fields = csn.fields();
while (fields.hasNext()) {
String property = fields.next().getKey();
switch (property) {
case CdsConstants.MAX:
targetMax = csn.get(property).asText();
break;
case CdsConstants.SRC:
sourceMax = csn.get(property).asText();
break;
case CdsConstants.MIN:
targetMin = csn.get(property).asText();
break;
default:
issueCollector.unrecognized(path,
"The association has a cardinality specification with an unrecognized property '%s'", property);
}
}
if (sourceMax == null) {
if (isComposition || targetMax.equals("*")) {
sourceMax = "1";
} else {
sourceMax = "*";
}
}
return CdsAssociationTypeBuilder.CardinalityImpl.create(sourceMax, targetMin, targetMax);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy