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.block;
018
019import net.tridentsdk.meta.component.ImmutableMetaCollection;
020import net.tridentsdk.meta.component.MetaCollection;
021import net.tridentsdk.meta.component.MetaFactory;
022import net.tridentsdk.meta.component.MetaOwner;
023
024import javax.annotation.concurrent.ThreadSafe;
025
026/**
027 * Implementation of a block meta owner which provides access to the collection factory
028 *
029 * @author The TridentSDK Team
030 * @since 0.4-alpha
031 */
032@ThreadSafe
033public abstract class AbstractBlockMetaOwner<T extends MetaOwner> implements BlockMetaOwner<T> {
034    private final MetaCollection<T> collection = collect();
035
036    /**
037     * Create the metadata storage collection
038     *
039     * @return the new collection
040     */
041    protected abstract MetaCollection<T> collect();
042
043    @Override
044    public <M extends BlockMeta<T>> M obtainMeta(Class<M> cls) {
045        return collection.get(cls);
046    }
047
048    @Override
049    public <M extends BlockMeta<T>> M newMetaIfNull(Class<M> cls) {
050        M meta = obtainMeta(cls);
051        if (meta == null) {
052            meta = MetaFactory.newValue(cls);
053
054            collection.put(cls, meta);
055        }
056
057        return meta;
058    }
059
060    @Override
061    public <M extends MetaOwner> MetaCollection<M> ownedMeta() {
062        return ImmutableMetaCollection.copyOf((MetaCollection<M>) collection);
063    }
064
065    @Override
066    public <M extends BlockMeta<T>> void applyMeta(M... meta) {
067        applyMeta(true, meta);
068    }
069
070    @Override
071    public <M extends BlockMeta<T>> boolean applyMeta(boolean replace, M... meta) {
072        if (replace) {
073            boolean success = true;
074            for (M m : meta) {
075                Class cls = m.getClass();
076                if (cls.getSimpleName().contains("Impl")) {
077                    cls = cls.getInterfaces()[0];
078                }
079
080                if (!collection.putIfAbsent(cls, m)) {
081                    success = false;
082                }
083            }
084            return success;
085        }
086
087        for (M m : meta) {
088            Class cls = m.getClass();
089            if (cls.getSimpleName().contains("Impl")) {
090                cls = cls.getInterfaces()[0];
091            }
092
093            collection.put(cls, m);
094        }
095        return true;
096    }
097
098    @Override
099    public void clearMeta() {
100        collection.clear();
101    }
102}