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

com.github.zeger_tak.enversvalidationplugin.validate.PrimaryKeyValidator Maven / Gradle / Ivy

Go to download

This is a Maven plugin that allows for easy validation of database auditing with Hibernate and is intended to be used by projects that do not always rely on Envers to create the audit history.

There is a newer version: 0.6
Show newest version
package com.github.zeger_tak.enversvalidationplugin.validate;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nonnull;

import com.github.zeger_tak.enversvalidationplugin.annotation.AuditTableInformationMap;
import com.github.zeger_tak.enversvalidationplugin.annotation.ConnectionProvider;
import com.github.zeger_tak.enversvalidationplugin.annotation.Parameterized;
import com.github.zeger_tak.enversvalidationplugin.annotation.TargetPhase;
import com.github.zeger_tak.enversvalidationplugin.annotation.Validate;
import com.github.zeger_tak.enversvalidationplugin.annotation.ValidationType;
import com.github.zeger_tak.enversvalidationplugin.connection.ConnectionProviderInstance;
import com.github.zeger_tak.enversvalidationplugin.connection.DatabaseQueries;
import com.github.zeger_tak.enversvalidationplugin.entities.AuditTableInformation;
import com.github.zeger_tak.enversvalidationplugin.exceptions.ValidationException;
import org.dbunit.dataset.DataSetException;

/**
 * The goal of this validator is described in its {@link Validate} methods:
 */
@ValidationType(TargetPhase.CONSTRAINTS)
public class PrimaryKeyValidator
{
	private final ConnectionProviderInstance connectionProvider;
	private final AuditTableInformation auditTableInformation;
	private final List primaryIdentifierColumnNamesAuditTable;
	private final List primaryIdentifierColumnNamesContentTable;

	public PrimaryKeyValidator(@ConnectionProvider ConnectionProviderInstance connectionProvider, @Nonnull AuditTableInformation auditTableInformation, @Nonnull List primaryIdentifierColumnNamesAuditTable, @Nonnull List primaryIdentifierColumnNamesContentTable)
	{
		this.connectionProvider = connectionProvider;
		this.auditTableInformation = auditTableInformation;
		this.primaryIdentifierColumnNamesAuditTable = primaryIdentifierColumnNamesAuditTable;
		this.primaryIdentifierColumnNamesContentTable = primaryIdentifierColumnNamesContentTable;
	}

	@Parameterized(name = "{index}: auditTableName: {1}", uniqueIdentifier = "{1}")
	public static List generateTestData(@Nonnull @ConnectionProvider ConnectionProviderInstance connectionProvider, @Nonnull @AuditTableInformationMap Map auditTableInformationMap) throws SQLException, DataSetException
	{
		final DatabaseQueries databaseQueries = connectionProvider.getQueries();

		final List testData = new ArrayList<>();
		for (Map.Entry auditTableInformation : auditTableInformationMap.entrySet())
		{
			final List primaryIdentifierColumnNamesAuditTable = databaseQueries.getPrimaryKeyColumnNames(auditTableInformation.getKey());
			final List primaryIdentifierColumnNameContentTable = databaseQueries.getPrimaryKeyColumnNames(auditTableInformation.getValue().getContentTableName());

			testData.add(new Object[] { connectionProvider, auditTableInformation.getValue(), primaryIdentifierColumnNamesAuditTable, primaryIdentifierColumnNameContentTable, });
		}

		return testData;
	}

	/**
	 * Validates that the primary of the audit table is valid.
	 * A valid primary key for an audit table consists of:
	 * - The columns matching the primary key columns of the content table.
	 * - The column holding a foreign key to the revision table.
	 * - The column holding the revision type value (Add/Modify/Remove)
	 */
	@Validate
	public void validateAuditTableHasAValidPrimaryKey()
	{
		if (primaryIdentifierColumnNamesAuditTable.isEmpty())
		{
			throw new ValidationException("Audit table " + auditTableInformation.getAuditTableName() + " has no primary key.");
		}

		final Set expectedAuditTablePrimaryKeyColumnNames = new HashSet<>(primaryIdentifierColumnNamesContentTable);
		final String revisionTableIdentifierColumnName = connectionProvider.getQueries().getRevisionTableIdentifierColumnName();
		expectedAuditTablePrimaryKeyColumnNames.add(revisionTableIdentifierColumnName);

		expectedAuditTablePrimaryKeyColumnNames.removeAll(primaryIdentifierColumnNamesAuditTable);

		if (!expectedAuditTablePrimaryKeyColumnNames.isEmpty())
		{
			throw new ValidationException(
					//@formatter:off
					"Audit table " + auditTableInformation.getAuditTableName() + " has a primary key that is not compromised of the primary key columns of the content table ["
					+ auditTableInformation.getContentTableName() + "] + [" + revisionTableIdentifierColumnName +
					"] the following columns are missing: " + expectedAuditTablePrimaryKeyColumnNames
					//@formatter:on
			);
		}

		final Set actualPrimaryKeyColumnsAuditTable = new HashSet<>(primaryIdentifierColumnNamesAuditTable);
		actualPrimaryKeyColumnsAuditTable.remove(revisionTableIdentifierColumnName);
		actualPrimaryKeyColumnsAuditTable.removeAll(primaryIdentifierColumnNamesContentTable);

		if (!actualPrimaryKeyColumnsAuditTable.isEmpty())
		{
			throw new ValidationException("The primary key of audit table " + auditTableInformation.getAuditTableName() + " is comprised of more columns than expected, the following columns were not expected: " + actualPrimaryKeyColumnsAuditTable + " this error may also be thrown if the content table has no primary key.");
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy