fillKeys(Account,ResultSet)   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
/*
2
 * This file is part of Araknemu.
3
 *
4
 * Araknemu is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * Araknemu is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with Araknemu.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2020 Vincent Quatrevieux
18
 */
19
20
package fr.quatrevieux.araknemu.data.living.repository.implementation.sql;
21
22
import fr.quatrevieux.araknemu.core.dbal.executor.QueryExecutor;
23
import fr.quatrevieux.araknemu.core.dbal.repository.EntityNotFoundException;
24
import fr.quatrevieux.araknemu.core.dbal.repository.Record;
25
import fr.quatrevieux.araknemu.core.dbal.repository.RepositoryException;
26
import fr.quatrevieux.araknemu.core.dbal.repository.RepositoryUtils;
27
import fr.quatrevieux.araknemu.data.living.entity.account.Account;
28
import fr.quatrevieux.araknemu.data.living.repository.account.AccountRepository;
29
import fr.quatrevieux.araknemu.data.living.transformer.PermissionsTransformer;
30
import org.apache.commons.lang3.StringUtils;
31
32
import java.sql.ResultSet;
33
import java.sql.SQLException;
34
import java.util.Collection;
35
import java.util.Collections;
36
import java.util.Optional;
37
38
final class SqlAccountRepository implements AccountRepository {
39
    private final QueryExecutor executor;
40
    private final RepositoryUtils<Account> utils;
41
    private final PermissionsTransformer permissionsTransformer;
42
43 1
    public SqlAccountRepository(QueryExecutor executor, PermissionsTransformer permissionsTransformer) {
44 1
        this.executor = executor;
45 1
        this.utils = new RepositoryUtils<>(this.executor, new Loader(permissionsTransformer));
46 1
        this.permissionsTransformer = permissionsTransformer;
47 1
    }
48
49
    @Override
50
    public void initialize() throws RepositoryException {
51
        try {
52 1
            executor.query(
53
                "CREATE TABLE ACCOUNT (" +
54
                    "ACCOUNT_ID INTEGER PRIMARY KEY AUTOINCREMENT," +
55
                    "USERNAME VARCHAR(32) UNIQUE," +
56
                    "PASSWORD VARCHAR(256)," +
57
                    "PSEUDO VARCHAR(32) UNIQUE," +
58
                    "PERMISSIONS INTEGER," +
59
                    "QUESTION VARCHAR(64)," +
60
                    "ANSWER VARCHAR(255)" +
61
                ")"
62
            );
63
        } catch (SQLException e) {
64
            throw new RepositoryException(e);
65 1
        }
66 1
    }
67
68
    @Override
69
    public void destroy() throws RepositoryException {
70
        try {
71 1
            executor.query("DROP TABLE ACCOUNT");
72
        } catch (SQLException e) {
73
            throw new RepositoryException(e);
74 1
        }
75 1
    }
76
77
    @Override
78
    public Account add(Account entity) {
79 1
        return utils.update(
80
            "INSERT INTO ACCOUNT (`USERNAME`, `PASSWORD`, `PSEUDO`, `PERMISSIONS`, `QUESTION`, `ANSWER`) VALUES (?, ?, ?, ?, ?, ?)",
81
            rs -> {
82 1
                rs.setString(1, entity.name());
83 1
                rs.setString(2, entity.password());
84 1
                rs.setString(3, entity.pseudo());
85 1
                rs.setInt(4,    permissionsTransformer.serialize(entity.permissions()));
86 1
                rs.setString(5, entity.question());
87 1
                rs.setString(6, entity.answer());
88 1
            },
89
            entity
90
        );
91
    }
92
93
    @Override
94
    public void delete(Account entity) {
95 1
        utils.update("DELETE FROM ACCOUNT WHERE ACCOUNT_ID = ?", rs -> rs.setInt(1, entity.id()));
96 1
    }
97
98
    @Override
99
    public Account get(Account entity) throws RepositoryException {
100 1
        return get(entity.id());
101
    }
102
103
    // @fixme not on the interface
0 ignored issues
show
Code Smell introduced by
Tasks associated with this FIXME comment should be completed and this comment removed.
Loading history...
104
    public Account get(int id) throws RepositoryException {
105 1
        return utils.findOne(
106
            "SELECT * FROM ACCOUNT WHERE ACCOUNT_ID = ?",
107 1
            stmt -> stmt.setInt(1, id)
108
        );
109
    }
110
111
    @Override
112
    public boolean has(Account entity) {
113 1
        return utils.aggregate(
114
            "SELECT COUNT(*) FROM ACCOUNT WHERE ACCOUNT_ID = ?",
115 1
            rs -> rs.setInt(1, entity.id())
116
        ) > 0;
117
    }
118
119
    @Override
120
    public Account findByUsername(String username) throws RepositoryException {
121 1
        return utils.findOne(
122
            "SELECT * FROM ACCOUNT WHERE USERNAME = ?",
123 1
            rs -> rs.setString(1, username)
124
        );
125
    }
126
127
    @Override
128
    public Optional<Account> findByPseudo(String pseudo) throws RepositoryException {
129
        try {
130 1
            return Optional.of(utils.findOne(
131
                "SELECT * FROM ACCOUNT WHERE PSEUDO = ?",
132 1
                stmt -> stmt.setString(1, pseudo)
133
            ));
134 1
        } catch (EntityNotFoundException e) {
135 1
            return Optional.empty();
136
        }
137
    }
138
139
    @Override
140
    public void savePassword(Account entity) {
141 1
        utils.update("UPDATE ACCOUNT SET PASSWORD = ? WHERE ACCOUNT_ID = ?", stmt -> {
142 1
            stmt.setString(1, entity.password());
143 1
            stmt.setInt(2, entity.id());
144 1
        });
145 1
    }
146
147
    @Override
148
    public Collection<Account> findByIds(int[] ids) {
149 1
        if (ids.length == 0) {
150 1
            return Collections.emptyList();
151
        }
152
153 1
        if (ids.length == 1) {
154
            try {
155 1
                return Collections.singleton(get(ids[0]));
156 1
            } catch (EntityNotFoundException e) {
157 1
                return Collections.emptyList();
158
            }
159
        }
160
161 1
        return utils.findAll(
162 1
            "SELECT * FROM ACCOUNT WHERE ACCOUNT_ID IN (" + StringUtils.repeat("?, ", ids.length - 1) + "?)",
163
            stmt -> {
164 1
                for (int i = 0; i < ids.length; ++i) {
165 1
                    stmt.setInt(i + 1, ids[i]);
166
                }
167 1
            }
168
        );
169
    }
170
171
    private static class Loader implements RepositoryUtils.Loader<Account> {
0 ignored issues
show
Comprehensibility introduced by
Class or interface names should not shadow other classes or interfaces. In general, shadowing is a bad practice as it makes code harder to understand. Consider renaming this class.
Loading history...
172
        private final PermissionsTransformer permissionsTransformer;
173
174 1
        public Loader(PermissionsTransformer permissionsTransformer) {
175 1
            this.permissionsTransformer = permissionsTransformer;
176 1
        }
177
178
        @Override
179
        public Account create(Record record) throws SQLException {
180 1
            return new Account(
181 1
                record.getInt("ACCOUNT_ID"),
182 1
                record.getString("USERNAME"),
183 1
                record.getString("PASSWORD"),
184 1
                record.getString("PSEUDO"),
185 1
                permissionsTransformer.unserialize(record.getInt("PERMISSIONS")),
186 1
                record.getString("QUESTION"),
187 1
                record.getString("ANSWER")
188
            );
189
        }
190
191
        @Override
192
        public Account fillKeys(Account entity, ResultSet keys) throws SQLException {
193 1
            return entity.withId(
194 1
                keys.getInt(1)
195
            );
196
        }
197
    }
198
}
199