001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package net.tridentsdk.meta.component;
018
019import javax.annotation.concurrent.ThreadSafe;
020import java.util.Map;
021import java.util.function.Consumer;
022
023/**
024 * Represents a collection of {@link Meta} objects
025 *
026 * @author The TridentSDK Team
027 * @since 0.4-alpha
028 */
029@ThreadSafe
030public interface MetaCollection<S> {
031    /**
032     * Obtains the metadata value from the component type specified
033     *
034     * @param cls the component type
035     * @param <T> the meta value type
036     * @return the meta value
037     */
038    <T extends Meta<S>> T get(Class<T> cls);
039
040    /**
041     * Puts the meta value into the collection, inferring the type
042     *
043     * @param meta the meta to put
044     * @param <T>  the meta type
045     */
046    <T extends Meta<S>> void put(T meta);
047
048    /**
049     * Puts the meta value into the collection if it does not exist as defined by {@link #contains(Class)}
050     *
051     * @param meta the meta value to put
052     * @param <T>  the meta type
053     * @return {@code true} if the operation changed the collection, {@code false} if it had no effect
054     */
055    <T extends Meta<S>> boolean putIfAbsent(T meta);
056
057    /**
058     * Puts a mapping of a meta class and the meta value into the collection, replacing the existing
059     * value if necessary
060     *
061     * @param cls  the meta type
062     * @param meta the meta value
063     * @param <T>  the meta value type
064     */
065    <T extends Meta<S>> void put(Class<T> cls, T meta);
066
067    /**
068     * Appends the meta mapping only if it does not already exist as defined by {@link #contains(Class)}.
069     * Otherwise has no effect.
070     *
071     * @param cls  the meta type
072     * @param meta the meta value
073     * @param <T>  the meta value type
074     * @return {@code true} if this operation changed the collection, {@code false} if it had no effect
075     */
076    <T extends Meta<S>> boolean putIfAbsent(Class<T> cls, T meta);
077
078    /**
079     * Obtains whether a mapping of the type provided exists within the collection
080     *
081     * @param cls the meta type
082     * @param <T> the meta value type
083     * @return {@code true} if it exists, {@code false} if it doesn't
084     */
085    <T extends Meta<S>> boolean contains(Class<T> cls);
086
087    /**
088     * Removes the meta tag from this collection
089     *
090     * @param cls the meta type to remove
091     * @param <T> the meta value type
092     * @return the meta value associated with the type, or {@code null} if this operation had no effect
093     */
094    <T extends Meta<S>> T remove(Class<T> cls);
095
096    /**
097     * Iterates the collection
098     *
099     * @param consumer the iteration function
100     */
101    void iterate(Consumer<Map.Entry<Class<? extends Meta<S>>, Meta<S>>> consumer);
102
103    /**
104     * Clear the meta collection of meta values
105     */
106    void clear();
107}