com.sap.cds.ql.impl.PathImpl Maven / Gradle / Ivy
/*******************************************************************
* © 2020 SAP SE or an SAP affiliate company. All rights reserved. *
*******************************************************************/
package com.sap.cds.ql.impl;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import com.google.common.collect.Maps;
import com.sap.cds.impl.builder.model.ExpressionImpl;
import com.sap.cds.impl.builder.model.StructuredTypeRefImpl;
import com.sap.cds.impl.parser.token.RefSegmentImpl;
import com.sap.cds.ql.RefSegment;
import com.sap.cds.ql.cqn.CqnElementRef;
import com.sap.cds.ql.cqn.CqnReference;
import com.sap.cds.ql.cqn.CqnReference.Segment;
import com.sap.cds.ql.cqn.Path;
import com.sap.cds.ql.cqn.ResolvedSegment;
import com.sap.cds.reflect.CdsElement;
import com.sap.cds.reflect.CdsStructuredType;
import com.sap.cds.util.CdsModelUtils;
public class PathImpl implements Path {
private final LinkedList segments;
public PathImpl(LinkedList segments) {
this.segments = segments;
}
@Override
public Iterator iterator() {
return segments.iterator();
}
@Override
public Iterator reverse() {
ListIterator li = segments.listIterator(segments.size());
return new Iterator() {
@Override
public boolean hasNext() {
return li.hasPrevious();
}
@Override
public ResolvedSegment next() { // NOSONAR
return li.previous();
}
};
}
public ResolvedSegment root() {
return segments.getFirst();
}
public ResolvedSegment target() {
return segments.getLast();
}
public Path append(CdsElement element, CdsStructuredType type) {
return append(element, type, new HashMap<>());
}
public Path append(CdsElement element, CdsStructuredType type, Map entry) {
LinkedList p = new LinkedList<>(segments);
p.add(new ResolvedSegImpl(element, type, entry));
return new PathImpl(p);
}
@Override
public CqnReference toRef() {
List segs = segments.stream().map(ResolvedSegment::segment).collect(Collectors.toList());
return StructuredTypeRefImpl.typeRef(segs);
}
@Override
public String toString() {
return toRef().toJson();
}
static class ResolvedSegImpl implements ResolvedSegment {
private Segment segment;
private final CdsElement element;
private final CdsStructuredType type;
private final Map filter;
ResolvedSegImpl(CdsElement element, CdsStructuredType type, Map filter) {
this.element = element;
this.type = type;
this.filter = filter;
}
ResolvedSegImpl(Segment segment, CdsStructuredType type) {
this.segment = segment;
this.element = null;
this.type = type;
this.filter = new HashMap<>();
}
@Override
public Segment segment() {
if (segment == null) {
RefSegment seg;
if (element == null) {
seg = RefSegmentImpl.refSegment(type.getQualifiedName());
} else {
seg = RefSegmentImpl.refSegment(element.getName());
}
Map values = keyValues();
if (values.isEmpty()) {
values = values();
}
if (!values.isEmpty()) {
seg.filter(ExpressionImpl.matching(values));
}
segment = seg;
}
return segment;
}
@Override
public CdsStructuredType type() {
return type;
}
@Override
public Map values() {
return filter;
}
@Override
public Map keys() {
return keyValues(true);
}
@Override
public Map keyValues() {
return keyValues(false);
}
private Map keyValues(boolean emptyToNull) {
Set keyNames = CdsModelUtils.keyNames(type);
Map values = values();
if (values.containsKey(CqnElementRef.$KEY)) {
String key = keyNames.iterator().next();
values.put(key, values.remove(CqnElementRef.$KEY));
}
if (emptyToNull) {
keyNames.forEach(k -> values.putIfAbsent(k, null));
}
return new HashMap<>(Maps.filterKeys(values, keyNames::contains));
}
@Override
public String toString() {
return segment().toJson();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy