/*
 * 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.jdbc.entity.status.query;

import org.spine3.server.entity.status.EntityStatus;
import org.spine3.server.storage.jdbc.DatabaseException;
import org.spine3.server.storage.jdbc.query.StorageQuery;
import org.spine3.server.storage.jdbc.util.ConnectionWrapper;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.spine3.base.Stringifiers.idToString;
import static org.spine3.server.storage.jdbc.Sql.BuildingBlock.EQUAL;
import static org.spine3.server.storage.jdbc.Sql.BuildingBlock.SEMICOLON;
import static org.spine3.server.storage.jdbc.Sql.Query.ALL_ATTRIBUTES;
import static org.spine3.server.storage.jdbc.Sql.Query.FROM;
import static org.spine3.server.storage.jdbc.Sql.Query.PLACEHOLDER;
import static org.spine3.server.storage.jdbc.Sql.Query.SELECT;
import static org.spine3.server.storage.jdbc.Sql.Query.WHERE;
import static org.spine3.server.storage.jdbc.entity.status.table.EntityStatusTable.ARCHIVED_COL_INDEX;
import static org.spine3.server.storage.jdbc.entity.status.table.EntityStatusTable.DELETED_COL_INDEX;
import static org.spine3.server.storage.jdbc.entity.status.table.EntityStatusTable.ID_COL;
import static org.spine3.server.storage.jdbc.entity.status.table.EntityStatusTable.TABLE_NAME;

/**
 * @author Dmytro Dashenkov.
 */
public class SelectEntityStatusQuery extends StorageQuery {

    private static final String SQL =
            SELECT.toString() + ALL_ATTRIBUTES +
                    FROM + TABLE_NAME +
                    WHERE + ID_COL + EQUAL + PLACEHOLDER + SEMICOLON;

    private final String id;

    protected SelectEntityStatusQuery(Builder builder) {
        super(builder);
        this.id = builder.id;
    }

    public EntityStatus execute() {
        final boolean archived;
        final boolean deleted;
        try (ConnectionWrapper connection = getConnection(false)) {
            final PreparedStatement statement = prepareStatement(connection);
            statement.setString(1, id);
            final ResultSet resultSet = statement.executeQuery();
            final boolean empty = !resultSet.next();
            if (empty) {
                return EntityStatus.getDefaultInstance();
            }
            archived = resultSet.getBoolean(ARCHIVED_COL_INDEX);
            deleted = resultSet.getBoolean(DELETED_COL_INDEX);
            statement.close();
            resultSet.close();
        } catch (SQLException e) {
            getLogger().error("Failed to read EntityStatus.", e);
            throw new DatabaseException(e);
        }
        final EntityStatus status = EntityStatus.newBuilder()
                                                .setArchived(archived)
                                                .setDeleted(deleted)
                                                .build();
        return status;
    }

    public static Builder newBuilder() {
        final Builder builder = new Builder();
        builder.setQuery(SQL);
        return builder;
    }

    public static class Builder extends StorageQuery.Builder<Builder, SelectEntityStatusQuery> {

        private String id;

        public Builder setId(Object id) {
            checkNotNull(id);
            final String stringId = idToString(id);
            this.id = stringId;
            return getThis();
        }

        @Override
        public SelectEntityStatusQuery build() {
            return new SelectEntityStatusQuery(this);
        }

        @Override
        protected Builder getThis() {
            return this;
        }
    }
}

@@ -1515,16 +1515,86 @@
 String;%0A
+import static org.spine3.server.storage.jdbc.Sql.BuildingBlock.COMMA;%0A
 import s
@@ -1655,16 +1655,16 @@
 .EQUAL;%0A
-
 import s
@@ -1733,79 +1733,8 @@
 ON;%0A
-import static org.spine3.server.storage.jdbc.Sql.Query.ALL_ATTRIBUTES;%0A
 impo
@@ -2074,30 +2074,24 @@
 ARCHIVED_COL
-_INDEX
 ;%0Aimport sta
@@ -2174,22 +2174,16 @@
 ETED_COL
-_INDEX
 ;%0Aimport
@@ -2536,21 +2536,41 @@
  + A
-LL_ATTRIBUTES
+RCHIVED_COL + COMMA + DELETED_COL
  +%0A 
@@ -3380,30 +3380,24 @@
 ARCHIVED_COL
-_INDEX
 );%0A         
@@ -3445,14 +3445,8 @@
 _COL
-_INDEX
 );%0A 

Make the query only to the columns required.