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

org.bitbucket.cowwoc.requirements.java.internal.ObjectCapabilitiesImpl Maven / Gradle / Ivy

/*
 * Copyright (c) 2019 Gili Tzabari
 * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
 */
package org.bitbucket.cowwoc.requirements.java.internal;

import org.bitbucket.cowwoc.requirements.java.Configuration;
import org.bitbucket.cowwoc.requirements.java.StringVerifier;
import org.bitbucket.cowwoc.requirements.java.capabilities.ObjectCapabilities;
import org.bitbucket.cowwoc.requirements.java.internal.scope.ApplicationScope;
import org.bitbucket.cowwoc.requirements.java.internal.util.ExceptionBuilder;
import org.bitbucket.cowwoc.requirements.java.internal.util.Objects;

import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Consumer;

/**
 * Extendable implementation of {@link ObjectCapabilities}.
 *
 * @param  the type of verifier that methods should return
 * @param  the type of the value
 */
public abstract class ObjectCapabilitiesImpl implements ObjectCapabilities
{
	protected final ApplicationScope scope;
	protected final String name;
	protected final T actual;
	protected final Configuration config;

	/**
	 * @param scope  the application configuration
	 * @param name   the name of the value
	 * @param actual the actual value
	 * @param config the instance configuration
	 * @throws AssertionError if {@code scope}, {@code name} or {@code config} are null. If {@code name} is
	 *                        empty.
	 */
	protected ObjectCapabilitiesImpl(ApplicationScope scope, String name, T actual, Configuration config)
	{
		assert (scope != null) : "scope may not be null";
		assert (name != null) : "name may not be null";
		assert (!name.isEmpty()) : "name may not be empty";
		assert (config != null) : "config may not be null";
		this.scope = scope;
		this.name = name;
		this.actual = actual;
		this.config = config;
	}

	/**
	 * @return this
	 */
	protected S getThis()
	{
		@SuppressWarnings("unchecked")
		S result = (S) this;
		return result;
	}

	@Override
	public S isEqualTo(Object expected)
	{
		if (Objects.equals(actual, expected))
			return getThis();

		ContextGenerator contextGenerator = new ContextGenerator(config,
			scope.getDiffGenerator());
		List> context = contextGenerator.getContext("Actual", actual, "Expected",
			expected);
		throw new ExceptionBuilder(scope, config, IllegalArgumentException.class,
			name + " had an unexpected value.").
			addContext(context).
			build();
	}

	@Override
	public S isEqualTo(Object expected, String name)
	{
		scope.getInternalVerifier().requireThat(name, "name").isNotNull().trim().isNotEmpty();
		if (Objects.equals(actual, expected))
			return getThis();

		ContextGenerator contextGenerator = new ContextGenerator(config, scope.getDiffGenerator());
		List> context = contextGenerator.getContext("Actual", actual, "Expected",
			expected);
		throw new ExceptionBuilder(scope, config, IllegalArgumentException.class,
			this.name + " must be equal to " + name + ".").
			addContext(context).
			build();
	}

	@Override
	public S isNotEqualTo(Object other)
	{
		if (!Objects.equals(actual, other))
			return getThis();

		String value = config.toString(other);
		throw new ExceptionBuilder(scope, config, IllegalArgumentException.class,
			name + " may not be equal to " + value).
			build();
	}

	@Override
	public S isNotEqualTo(Object other, String name)
	{
		scope.getInternalVerifier().requireThat(name, "name").isNotNull().trim().isNotEmpty();
		if (!Objects.equals(actual, other))
			return getThis();

		throw new ExceptionBuilder(scope, config, IllegalArgumentException.class,
			this.name + " may not be equal to " + name + ".").
			addContext("Actual", actual).
			build();
	}

	@Override
	public S isSameObjectAs(Object expected, String name)
	{
		scope.getInternalVerifier().requireThat(name, "name").isNotNull().trim().isNotEmpty();
		if (actual == expected)
			return getThis();

		ContextGenerator contextGenerator = new ContextGenerator(config, scope.getDiffGenerator());
		List> context = contextGenerator.getContext("Actual", actual, "Expected",
			expected);
		throw new ExceptionBuilder(scope, config, IllegalArgumentException.class,
			this.name + " must be the same object as " + name + ".").
			addContext(context).
			build();
	}

	@Override
	public S isNotSameObjectAs(Object other, String name)
	{
		scope.getInternalVerifier().requireThat(name, "name").isNotNull().trim().isNotEmpty();
		if (actual != other)
			return getThis();

		throw new ExceptionBuilder(scope, config, IllegalArgumentException.class,
			this.name + " may not be the same object as " + name + ".").
			addContext("Actual", actual).
			build();
	}

	@Override
	public S isOneOf(Collection collection)
	{
		scope.getInternalVerifier().requireThat(collection, "collection").isNotNull();
		if (collection.contains(actual))
			return getThis();

		String collectionAsString = config.toString(collection);
		throw new ExceptionBuilder(scope, config, IllegalArgumentException.class,
			this.name + " must be one of " + collectionAsString + ".").
			addContext("Actual", actual).
			build();
	}

	@Override
	public S isNotOneOf(Collection collection)
	{
		scope.getInternalVerifier().requireThat(collection, "collection").isNotNull();
		if (!collection.contains(actual))
			return getThis();

		String collectionAsString = config.toString(collection);
		throw new ExceptionBuilder(scope, config, IllegalArgumentException.class,
			this.name + " may not be one of " + collectionAsString + ".").
			addContext("Actual", actual).
			build();
	}

	@Override
	public S isInstanceOf(Class type)
	{
		scope.getInternalVerifier().requireThat(type, "type").isNotNull();
		if (type.isInstance(actual))
			return getThis();

		String actualClass;
		if (actual == null)
			actualClass = "null";
		else
			actualClass = actual.getClass().getName();
		throw new ExceptionBuilder(scope, config, IllegalArgumentException.class,
			name + " must be an instance of " + type.getName() + ".").
			addContext("Actual.getClass()", actualClass).
			addContext("Actual", actual).
			build();
	}

	@Override
	public S isNotInstanceOf(Class type)
	{
		scope.getInternalVerifier().requireThat(type, "type").isNotNull();
		if (!type.isInstance(actual))
			return getThis();

		String actualClass = actual.getClass().getName();
		throw new ExceptionBuilder(scope, config, IllegalArgumentException.class,
			name + " may not be an instance of " + type.getName() + ".").
			addContext("Actual.getClass()", actualClass).
			addContext("Actual", actual).
			build();
	}

	@Override
	public S isNull()
	{
		if (actual == null)
			return getThis();

		// Output a diff because actual.toString() may return "null" which is misleading
		ContextGenerator contextGenerator = new ContextGenerator(config, scope.getDiffGenerator());
		List> context = contextGenerator.getContext("Actual", actual, "Expected",
			null);
		throw new ExceptionBuilder(scope, config, IllegalArgumentException.class,
			name + " must be null.").
			addContext(context).
			build();
	}

	@Override
	public S isNotNull()
	{
		if (actual != null)
			return getThis();

		throw new ExceptionBuilder(scope, config, NullPointerException.class,
			name + " may not be null").
			build();
	}

	@Override
	public StringVerifier asString()
	{
		String value = config.toString(actual);
		return new StringVerifierImpl(scope, name, value, config);
	}

	@Override
	public S asString(Consumer consumer)
	{
		consumer.accept(asString());
		return getThis();
	}

	@Override
	public Optional getActualIfPresent()
	{
		return Optional.of(actual);
	}

	@Override
	public T getActual()
	{
		return actual;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy