/*
 * Copyright 2017, TeamDev Ltd. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.spine3.server.storage.memory;

import org.spine3.server.aggregate.Aggregate;
import org.spine3.server.aggregate.AggregateStorage;
import org.spine3.server.entity.Entity;
import org.spine3.server.entity.storage.ColumnTypeRegistry;
import org.spine3.server.projection.ProjectionStorage;
import org.spine3.server.stand.StandStorage;
import org.spine3.server.storage.RecordStorage;
import org.spine3.server.storage.StorageFactory;

/**
 * A factory for in-memory storages.
 *
 * @author Alexander Yevsyukov
 */
public class InMemoryStorageFactory implements StorageFactory {

    private final boolean multitenant;

    private InMemoryStorageFactory(boolean multitenant) {
        this.multitenant = multitenant;
    }

    @Override
    public boolean isMultitenant() {
        return this.multitenant;
    }

    /**
     * {@inheritDoc}
     *
     * <p>In-memory implementation stores no values separately
     * ({@link org.spine3.server.entity.storage.Column Columns}), therefore
     * returns {@linkplain ColumnTypeRegistry#empty() an empty ColumnTypeRegistry}.
     */
    @Override
    public ColumnTypeRegistry getTypeRegistry() {
        return ColumnTypeRegistry.newBuilder()
                                 .build();
    }

    @Override
    public StandStorage createStandStorage() {
        final InMemoryStandStorage result = InMemoryStandStorage.newBuilder()
                                                                .setMultitenant(isMultitenant())
                                                                .build();
        return result;
    }

    /** NOTE: the parameter is unused. */
    @Override
    public <I> AggregateStorage<I> createAggregateStorage(
            Class<? extends Aggregate<I, ?, ?>> unused) {
        return new InMemoryAggregateStorage<>(isMultitenant());
    }

    /**
     * {@inheritDoc}
     *
     * @param unused the parameter is not used in this implementation
     */
    @Override
    public <I> RecordStorage<I> createRecordStorage(Class<? extends Entity<I, ?>> unused) {
        return InMemoryRecordStorage.newInstance(isMultitenant());
    }

    @Override
    public <I> ProjectionStorage<I> createProjectionStorage(Class<? extends Entity<I, ?>> unused) {
        final boolean multitenant = isMultitenant();
        final InMemoryRecordStorage<I> entityStorage =
                InMemoryRecordStorage.newInstance(multitenant);
        return InMemoryProjectionStorage.newInstance(entityStorage);
    }

    @Override
    public void close() {
        // NOP
    }

    @Override
    public StorageFactory toSingleTenant() {
        if (!isMultitenant()) {
            return this;
        }
        return getInstance(false);
    }

    public static InMemoryStorageFactory getInstance(boolean multitenant) {
        return multitenant
                ? Singleton.INSTANCE.multiTenantInstance
                : Singleton.INSTANCE.singleTenantInstance;
    }

    @SuppressWarnings("NonSerializableFieldInSerializableClass")
    private enum Singleton {
        INSTANCE;
        private final InMemoryStorageFactory singleTenantInstance =
                new InMemoryStorageFactory(false);

        private final InMemoryStorageFactory multiTenantInstance =
                new InMemoryStorageFactory(true);
    }
}

@@ -2023,47 +2023,8 @@
 urns
- %7B@linkplain ColumnTypeRegistry#empty()
  an 
@@ -2047,17 +2047,16 @@
 Registry
-%7D
 .%0A     *

Fix javadoc error.