package jalse.attributes;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* This is an attribute collection. This attribute collections works more like a set but using the
* {@link AttributeType} to determine uniqueness (only one of each attribute type can be added).
* {@link AttributeListener} can be added for an attribute type, trigger code will fire upon add,
* update or removal of attributes of that type. Each collection manipulation method returns
* {@code Optional} of the attribute (may be empty if none matching are found).
*
* @author Elliot Ford
*
* @see Optional
* @see DefaultAttributeContainer
* @see Attributes#emptyAttributeContainer()
* @see Attributes#unmodifiableAttributeContainer(AttributeContainer)
*
*/
public interface AttributeContainer {
/**
* Adds all attributes and listeners from the source container.
*
* @param sourceContainer
* Source container to copy from.
*/
default void addAll(final AttributeContainer sourceContainer) {
addAllAttributes(sourceContainer);
addAllAttributeListeners(sourceContainer);
}
/**
* Adds all attribute listeners from the source container.
*
* @param sourceContainer
* Source attribute container.
*/
@SuppressWarnings("unchecked")
default void addAllAttributeListeners(final AttributeContainer sourceContainer) {
for (final NamedAttributeType<?> namedType : sourceContainer.getAttributeListenerTypes()) {
for (final AttributeListener<?> listener : sourceContainer.getAttributeListeners(namedType)) {
addAttributeListener((NamedAttributeType<Object>) namedType, (AttributeListener<Object>) listener);
}
}
}
/**
* Adds all attributes from the source container.
*
* @param sourceContainer
* Source attribute container.
*/
@SuppressWarnings("unchecked")
default void addAllAttributes(final AttributeContainer sourceContainer) {
for (final NamedAttributeType<?> namedType : sourceContainer.getAttributeTypes()) {
final Object attr = sourceContainer.getAttribute(namedType);
if (attr != null) {
setAttribute((NamedAttributeType<Object>) namedType, attr);
}
}
}
/**
* Adds an attribute listener for the supplied named attribute type.
*
* @param namedType
* Named attribute type.
* @param listener
* Listener to add.
* @return Whether the listener was not already assigned.
*/
<T> boolean addAttributeListener(final NamedAttributeType<T> namedType, final AttributeListener<T> listener);
/**
* Adds an attribute listener for the supplied attribute type.
*
* @param name
* Attribute type name.
*
* @param type
* Attribute type.
* @param listener
* Listener to add.
* @return Whether the listener was not already assigned.
*
* @see #addAttributeListener(NamedAttributeType, AttributeListener)
*/
default <T> boolean addAttributeListener(final String name, final AttributeType<T> type,
final AttributeListener<T> listener) {
return addAttributeListener(new NamedAttributeType<>(name, type), listener);
}
/**
* Manually fires an attribute change for the supplied attribute type. This is used for mutable
* attributes that can change their internal state.
*
* @param namedType
* Named attribute type name.
*/
<T> void fireAttributeChanged(final NamedAttributeType<T> namedType);
/**
* Manually fires an attribute change for the supplied attribute type. This is used for mutable
* attributes that can change their internal state.
*
* @param name
* Attribute type name.
*
* @param type
* Attribute type to fire for.
*
* @see #fireAttributeChanged(NamedAttributeType)
*/
default <T> void fireAttributeChanged(final String name, final AttributeType<T> type) {
fireAttributeChanged(new NamedAttributeType<>(name, type));
}
/**
* Gets the attribute matching the supplied type.
*
* @param namedType
* Named attribute type to check for.
* @return The attribute matching the supplied type or null if none found.
*/
<T> T getAttribute(final NamedAttributeType<T> namedType);
/**
* Gets the attribute matching the supplied type.
*
* @param name
* Attribute type name.
*
* @param type
* Attribute type to check for.
* @return The attribute matching the supplied type or null if none found.
*
* @see #getAttribute(NamedAttributeType)
*/
default <T> T getAttribute(final String name, final AttributeType<T> type) {
return getAttribute(new NamedAttributeType<>(name, type));
}
/**
* Gets the number of total attributes within the container.
*
* @return Attribute count.
*/
int getAttributeCount();
/**
* Gets the attribute type names with listeners associated.
*
* @return Associated attribute type names to listeners.
*
* @see #getAttributeListenerTypes()
*/
default Set<String> getAttributeListenerNames() {
return getAttributeListenerTypes().stream().map(NamedAttributeType::getName).collect(Collectors.toSet());
}
/**
* Gets all attribute listeners associated to the supplied named attribute type.
*
* @param namedType
* Named attribute type to check for.
* @return Set of attribute listeners or an empty set if none were found.
*/
<T> Set<? extends AttributeListener<T>> getAttributeListeners(final NamedAttributeType<T> namedType);
/**
* Gets all attribute listeners associated to the supplied named attribute type.
*
* @param name
* Attribute type name.
*
* @param type
* Attribute type to check for.
* @return Set of attribute listeners or an empty set if none were found.
*
* @see #getAttributeListeners(NamedAttributeType)
*/
default <T> Set<? extends AttributeListener<T>> getAttributeListeners(final String name,
final AttributeType<T> type) {
return getAttributeListeners(new NamedAttributeType<>(name, type));
}
/**
* Gets all of the named attribute types with listeners bound.
*
* @return All named types with listeners.
*/
Set<NamedAttributeType<?>> getAttributeListenerTypes();
/**
* Gets all the attribute listener types.
*
* @param name
* Attribute type name.
*
* @return Set of the types attribute listeners are for or an empty set if none were found.
* @see #getAttributeListenerTypes
*/
default Set<AttributeType<?>> getAttributeListenerTypes(final String name) {
return getAttributeListenerTypes().stream().filter(nt -> name.equals(nt.getName()))
.map(NamedAttributeType::getType).collect(Collectors.toSet());
}
/**
* Gets all the attribute type names assigned to attributes.
*
* @return Attribute type names with values.
*
* @see #getAttributeTypes()
*/
default Set<String> getAttributeNames() {
return getAttributeTypes().stream().map(NamedAttributeType::getName).collect(Collectors.toSet());
}
/**
* Gets all of the attributes within the container.
*
* @return All of the attributes or an empty set if none were found.
*
* @see #streamAttributes()
*/
default Set<?> getAttributes() {
return streamAttributes().collect(Collectors.toSet());
}
/**
* Gets all of the named attribute types with attributes.
*
* @return Named attribute types for the attributes.
*/
Set<NamedAttributeType<?>> getAttributeTypes();
/**
* Gets all of the attribute types within the container.
*
* @param name
* Attribute type name.
*
* @return All of the types of the attributes or an empty set if none were found.
*
* @see #getAttributeTypes()
*/
default Set<AttributeType<?>> getAttributeTypes(final String name) {
return getAttributeTypes().stream().filter(nt -> name.equals(nt.getName())).map(NamedAttributeType::getType)
.collect(Collectors.toSet());
}
/**
* This is a convenience method for getting an attribute (optional).
*
*
* @param namedType
* Named attribute type to check for.
* @return Optional containing the attribute or else empty optional if none found.
*
* @see #getAttribute(NamedAttributeType)
*/
default <T> Optional<T> getOptAttribute(final NamedAttributeType<T> namedType) {
return Optional.ofNullable(getAttribute(namedType));
}
/**
* This is a convenience method for getting an attribute (optional).
*
* @param name
* Attribute type name.
* @param type
* Attribute type to check for.
* @return Optional containing the attribute or else empty optional if none found.
*
* @see #getOptAttribute(NamedAttributeType)
*/
default <T> Optional<T> getOptAttribute(final String name, final AttributeType<T> type) {
return getOptAttribute(new NamedAttributeType<>(name, type));
}
/**
* Checks whether the container has a value associated to the supplied attribute type.
*
* @param namedType
* Named attribute type.
* @return Whether the attribute was found.
*
* @see #getAttribute(NamedAttributeType)
*/
default <T> boolean hasAttribute(final NamedAttributeType<T> namedType) {
return getAttribute(namedType) != null;
}
/**
* Checks whether the container has a value associated to the supplied attribute type.
*
* @param name
* Attribute type name.
* @param type
* Attribute type.
* @return Whether the attribute was found.
*
* @see #hasAttribute(NamedAttributeType)
*/
default <T> boolean hasAttribute(final String name, final AttributeType<T> type) {
return hasAttribute(new NamedAttributeType<>(name, type));
}
/**
* Checks whether the container contains a particular listener for a given attribute type.
*
* @param namedType
* Named attribute type.
* @param listener
* Listener to check presence of.
* @return Whether the attribute has any listeners.
*/
default <T> boolean hasAttributeListener(final NamedAttributeType<T> namedType,
final AttributeListener<T> listener) {
return getAttributeListeners(namedType).contains(listener);
}
/**
* Checks whether the container contains a particular listener for a given attribute type.
*
* @param name
* Attribute type name.
* @param type
* Attribute type.
* @param listener
* Listener to check presence of.
* @return Whether the attribute has any listeners.
*
* @see #hasAttributeListener(NamedAttributeType, AttributeListener)
*/
default <T> boolean hasAttributeListener(final String name, final AttributeType<T> type,
final AttributeListener<T> listener) {
return hasAttributeListener(new NamedAttributeType<>(name, type), listener);
}
/**
* Checks whether the container contains any listeners for a given attribute type.
*
* @param namedType
* Named attribute type.
* @return Whether the attribute has any listeners.
*/
default <T> boolean hasAttributeListeners(final NamedAttributeType<T> namedType) {
return !getAttributeListeners(namedType).isEmpty();
}
/**
* Checks whether the container contains any listeners for a given attribute type.
*
* @param name
* Attribute type name.
* @param type
* Attribute type.
* @return Whether the attribute has any listeners.
*
* @see #hasAttributeListeners(NamedAttributeType)
*/
default <T> boolean hasAttributeListeners(final String name, final AttributeType<T> type) {
return hasAttributeListeners(new NamedAttributeType<>(name, type));
}
/**
* Checks whether the container has any attributes.
*
* @return Is the container is not empty.
*/
default boolean hasAttributes() {
return getAttributeCount() > 0;
}
/**
* Removes the attribute matching the supplied type.
*
* @param namedType
* Named attribute type to remove.
*
* @return The removed attribute or null if none was removed.
*/
<T> T removeAttribute(final NamedAttributeType<T> namedType);
/**
* Removes the attribute matching the supplied type.
*
* @param name
* Attribute type name.
*
* @param type
* Attribute type to remove.
* @return The removed attribute or null if none was removed.
*
* @see #removeAttribute(NamedAttributeType)
*/
default <T> T removeAttribute(final String name, final AttributeType<T> type) {
return removeAttribute(new NamedAttributeType<>(name, type));
}
/**
* Removes an attribute listener assigned to the supplied attribute type.
*
* @param namedType
* Named attribute type.
* @param listener
* Listener to remove.
* @return Whether the listener was assigned.
*/
<T> boolean removeAttributeListener(final NamedAttributeType<T> namedType, final AttributeListener<T> listener);
/**
* Removes an attribute listener assigned to the supplied attribute type.
*
* @param name
* Attribute type name.
* @param type
* Attribute type.
* @param listener
* Listener to remove.
* @return Whether the listener was assigned.
*/
default <T> boolean removeAttributeListener(final String name, final AttributeType<T> type,
final AttributeListener<T> listener) {
return removeAttributeListener(new NamedAttributeType<>(name, type), listener);
}
/**
* Removes all listeners.
*/
void removeAttributeListeners();
/**
* Removes all listeners for the supplied attribute types.
*
* @param namedType
* Named attribute type.
*/
<T> void removeAttributeListeners(final NamedAttributeType<T> namedType);
/**
* Removes all listeners for the supplied attribute types.
*
* @param name
* Attribute type name.
* @param type
* Attribute type.
*
* @see #removeAttributeListeners(NamedAttributeType)
*/
default <T> void removeAttributeListeners(final String name, final AttributeType<T> type) {
removeAttributeListeners(new NamedAttributeType<>(name, type));
}
/**
* Removes all attributes within the container (firing removal events).
*/
void removeAttributes();
/**
* This is a convenience method for removing an attribute (no optional).
*
* @param namedType
* Named attribute type to remove.
* @return Optional containing the removed attribute or else empty optional if none found
*/
default <T> Optional<T> removeOptAttribute(final NamedAttributeType<T> namedType) {
return Optional.ofNullable(removeAttribute(namedType));
}
/**
* This is a convenience method for removing an attribute (no optional).
*
* @param name
* Attribute type name.
*
* @param type
* Attribute type to remove.
* @return Optional containing the removed attribute or else empty optional if none found
*
* @see #removeOptAttribute(NamedAttributeType)
*/
default <T> Optional<T> removeOptAttribute(final String name, final AttributeType<T> type) {
return removeOptAttribute(new NamedAttributeType<>(name, type));
}
/**
* Adds the supplied attribute to the collection.
*
* @param namedType
* Named attribute type.
* @param attr
* Attribute to add.
* @return The replaced attribute or null if none was replaced.
*/
<T> T setAttribute(final NamedAttributeType<T> namedType, final T attr);
/**
* Adds the supplied attribute to the collection.
*
* @param name
* Attribute type name.
*
* @param type
* Attribute type.
* @param attr
* Attribute to add.
* @return The replaced attribute or null if none was replaced.
*
* @see #setAttribute(NamedAttributeType, Object)
*/
default <T> T setAttribute(final String name, final AttributeType<T> type, final T attr) {
return setAttribute(new NamedAttributeType<>(name, type), attr);
}
/**
* This is a convenience method for adding an attribute (optional).
*
* @param namedType
* Named attribute type.
* @param attr
* Attribute to add.
* @return Optional containing the replaced attribute if set or else empty optional if none
* found
*
*/
default <T> Optional<T> setOptAttribute(final NamedAttributeType<T> namedType, final T attr) {
return Optional.ofNullable(setAttribute(namedType, attr));
}
/**
* This is a convenience method for adding an attribute (optional).
*
* @param name
* Attribute type name.
*
* @param type
* Attribute type.
* @param attr
* Attribute to add.
* @return Optional containing the replaced attribute if set or else empty optional if none
* found
*
* @see #setOptAttribute(NamedAttributeType, Object)
*/
default <T> Optional<T> setOptAttribute(final String name, final AttributeType<T> type, final T attr) {
return setOptAttribute(new NamedAttributeType<>(name, type), attr);
}
/**
* Streams all of the attributes within the container.
*
* @return Stream of all attributes.
*/
Stream<?> streamAttributes();
}