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

com.sap.cds.impl.ExceptionHandler 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;

import static com.sap.cds.reflect.impl.CdsAnnotatableImpl.removeAt;
import static com.sap.cds.reflect.impl.reader.model.CdsConstants.ANNOTATION_VALID_FROM;
import static com.sap.cds.util.CdsModelUtils.keyNames;

import java.sql.BatchUpdateException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.sap.cds.CdsDataStoreException;
import com.sap.cds.CdsException;
import com.sap.cds.NotNullConstraintException;
import com.sap.cds.UniqueConstraintException;
import com.sap.cds.jdbc.spi.ExceptionAnalyzer;
import com.sap.cds.reflect.CdsElement;
import com.sap.cds.reflect.CdsEntity;

public class ExceptionHandler {
	private final CdsEntity entity;
	private final ExceptionAnalyzer exceptionAnalyzer;

	public ExceptionHandler(CdsEntity entity, ExceptionAnalyzer exceptionAnalyzer) {
		this.entity = entity;
		this.exceptionAnalyzer = exceptionAnalyzer;
	}

	public CdsException cdsBatchException(List> entries, int updatedCount,
			BatchUpdateException ex) {
		if (exceptionAnalyzer.isUniqueConstraint(ex)) {
			return new BatchExceptionHandler(entity).uniqueConstraint(entries, updatedCount, ex);
		}
		if (exceptionAnalyzer.isNotNullConstraint(ex)) {
			return new BatchExceptionHandler(entity).notNullConstraint(entries, updatedCount, ex);
		}
		return new CdsDataStoreException("Error executing the statement", ex);
	}

	public CdsException cdsException(Map entryValues, Exception ex) {
		Throwable cause = ExceptionAnalyzer.getRootCause(ex);
		if (cause instanceof SQLException) {
			SQLException sqlEx = (SQLException) cause;
			if (exceptionAnalyzer.isUniqueConstraint(sqlEx)) {
				return new UniqueConstraintException(entity, entryValues, keyNames(entity), ex);
			}
			if (exceptionAnalyzer.isNotNullConstraint(sqlEx)) {
				return notNullConstraintException(entity, entryValues, ex);
			}
		}
		return new CdsDataStoreException("Error executing the statement", ex);
	}

	public static void chainNextExceptions(SQLException ex) {
		SQLException next = ex.getNextException();
		if (ex.getCause() == null && next != null) {
			ex.initCause(next);
		}
	}

	private static List getNullValuedNotNullableElements(CdsEntity entity, Map entry) {
		Stream nullKeys = entity.keyElements().filter(e -> null == entry.get(e.getName()));
		Stream notNullEls = entity.elements()
				.filter(e -> (e.isNotNull() || e.findAnnotation(removeAt(ANNOTATION_VALID_FROM)).isPresent())
						&& null == entry.get(e.getName()));

		return Stream.concat(nullKeys, notNullEls).collect(Collectors.toList());
	}

	private static CdsException notNullConstraintException(CdsEntity entity, Map entryValues, Exception ex) {
		List nonNullableElements = getNullValuedNotNullableElements(entity, entryValues);
		if (nonNullableElements.isEmpty()) {
			return new CdsDataStoreException("Error executing the statement", ex);
		}
		return new NotNullConstraintException(nonNullableElements, ex);
	}

	static class BatchExceptionHandler {

		private final CdsEntity entity;

		public BatchExceptionHandler(CdsEntity entity) {
			this.entity = entity;
		}

		private int getFirstNonPositiveIndex(int[] rcs) {
			for (int pos = 0; pos < rcs.length; pos++) {
				if (rcs[pos] < 0) {
					return pos;
				}
			}

			return rcs.length;
		}

		public CdsException uniqueConstraint(List> entries, int updatedCount,
				BatchUpdateException ex) {
			int[] updateCounts = ex.getUpdateCounts();
			int badPos = getFirstNonPositiveIndex(updateCounts);
			Map entry = entries.get(badPos + updatedCount);

			return new UniqueConstraintException(entity, entry, keyNames(entity), ex);
		}

		public CdsException notNullConstraint(List> entries, int updatedCount,
				BatchUpdateException ex) {
			int[] updateCounts = ex.getUpdateCounts();
			int badPos = getFirstNonPositiveIndex(updateCounts);
			Map entryValues = entries.get(badPos + updatedCount);

			return notNullConstraintException(entity, entryValues, ex);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy