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

org.perfectable.introspection.bean.Property Maven / Gradle / Ivy

There is a newer version: 5.1.0
Show newest version
package org.perfectable.introspection.bean;

import java.lang.reflect.Type;
import java.util.Objects;
import javax.annotation.Nullable;

import static java.util.Objects.requireNonNull;

/**
 * Represents a property of a bean.
 *
 * @param  Bean type that has this property
 * @param  Type of property value
 */
public final class Property {
	private final B bean;
	private final PropertySchema schema;

	static  Property of(B bean, PropertySchema schema) {
		requireNonNull(bean);
		requireNonNull(schema);
		return new Property<>(bean, schema);
	}

	private Property(B bean, PropertySchema schema) {
		this.bean = bean;
		this.schema = schema;
	}

	/**
	 * Safely casts expected value to specific type.
	 *
	 * @param newValueType new value type representation
	 * @param  new value type
	 * @return property with new value type
	 * @throws IllegalArgumentException if property value aren't of this type.
	 */
	public  Property as(Class newValueType) {
		return schema.as(newValueType).bind(bean);
	}

	/**
	 * Extracts value of this property from bound bean.
	 *
	 * @return Property value
	 * @throws IllegalStateException when this property is not readable
	 */
	@Nullable
	public T get() {
		return schema.get(this.bean);
	}

	/**
	 * Sets provided value for this property of bound bean.
	 *
	 * @param value new value for this property
	 * @throws IllegalStateException when this property is not writeable
	 */
	public void set(@Nullable T value) {
		schema.set(bean, value);
	}

	/**
	 * Extracts type of the property.
	 *
	 * @return property type
	 */
	public Type type() {
		return schema.type();
	}

	/**
	 * Extracts name of the property.
	 *
	 * @return property name
	 */
	public String name() {
		return schema.name();
	}

	/**
	 * Answers if the property is readable, i.e. {@link #get} will succeed.
	 *
	 * @return if the property can have value read
	 */
	public boolean isReadable() {
		return schema.isReadable();
	}

	/**
	 * Answers if the property is writeable, i.e. {@link #set} will succeed.
	 *
	 * @return if the property can have value written
	 */
	public boolean isWritable() {
		return schema.isWritable();
	}

	/**
	 * Copies value of this property to same property of another bean.
	 *
	 * @param other bean to set value on
	 * @throws IllegalStateException when this property is either not readable or not writeable
	 */
	public void copy(Bean other) {
		T value = get();
		this.schema.set(other.contents(), value);
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof Property)) {
			return false;
		}
		Property other = (Property) obj;
		return Objects.equals(schema, other.schema)
			&& Objects.equals(bean, other.bean);
	}

	@Override
	public int hashCode() {
		return Objects.hash(schema, bean);
	}
}