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

com.sap.cds.impl.qat.QatNode Maven / Gradle / Ivy

There is a newer version: 3.4.0
Show newest version
/*******************************************************************
 * © 2019 SAP SE or an SAP affiliate company. All rights reserved. *
 *******************************************************************/
package com.sap.cds.impl.qat;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;

import com.sap.cds.ql.cqn.CqnPredicate;

public abstract class QatNode {

	private final QatNode parent;
	private final Map children = new LinkedHashMap<>();

	public QatNode(QatNode parent) {
		this.parent = parent;
	}

	public abstract String name();

	public abstract boolean inSource();

	public abstract void accept(QatVisitor visitor);

	public QatNode parent() {
		return parent;
	}

	public Collection children() {
		return Collections.unmodifiableCollection(children.values());
	}

	public boolean hasChildren() {
		return !children().isEmpty();
	}

	public QatNode child(String name, Optional filter) {
		return children.get(new Key(name, filter));
	}

	@SuppressWarnings("unchecked")
	public  T addChild(T child, Optional filter) {
		Key key = new Key(child.name(), filter);
		children.putIfAbsent(key, child);
		QatNode node = children.get(key);
		propagateInSource(child, node);
		try {
			return (T) node;
		} catch (ClassCastException ex) {
			throw new IllegalStateException("Query association tree contains element " + child.name()
					+ " with unexpected type " + node.getClass().getName(), ex);
		}
	}

	private static void propagateInSource(QatNode newNode, QatNode existingNode) {
		if (newNode != existingNode &&
				newNode instanceof QatEntityNode newEntityNode &&
				existingNode instanceof QatEntityNode existingEntityNode &&
				newEntityNode.inSource() == true &&
				existingEntityNode.inSource() == false) {
			existingEntityNode.setInSource();
		}
	}

	public  T addChild(T child) {
		return addChild(child, Optional.empty());
	}

	public static class Key {
		final String name;
		final String filterAsJson;
		final int hashCode;

		public Key(String name, Optional filter) {
			this.name = name;
			this.filterAsJson = filter.map(CqnPredicate::toJson).orElse("[]");
			this.hashCode = calculateHash(name, filterAsJson);
		}

		@Override
		public int hashCode() {
			return hashCode;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null) {
				return false;
			}
			if (obj.getClass() != this.getClass())
				return false;
			Key other = (Key) obj;
			if (hashCode != other.hashCode) {
				return false;
			}
			if (!name.equals(other.name))
				return false;
			return filterAsJson.equals(other.filterAsJson);
		}

		private static int calculateHash(String name, String filterAsJson) {
			final int prime = 31;
			int result = 1;
			result = prime * result + filterAsJson.hashCode();
			result = prime * result + name.hashCode();
			return result;
		}

	}

	@Override
	public String toString() {
		return name();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy