All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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