fr.quatrevieux.araknemu.data.world.repository.implementation.sql.SqlMapTemplateRepository   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Test Coverage

Coverage 87.8%

Importance

Changes 0
Metric Value
eloc 78
c 0
b 0
f 0
dl 0
loc 108
ccs 36
cts 41
cp 0.878
rs 10
wmc 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A initialize() 0 23 2
A Loader.fillKeys(MapTemplate,ResultSet) 0 3 1
A has(MapTemplate) 0 6 1
A SqlMapTemplateRepository(QueryExecutor,Transformer,Transformer) 0 6 1
A all() 0 3 1
A destroy() 0 6 2
A get(int) 0 5 1
A byGeolocation(Geolocation) 0 5 1
A get(MapTemplate) 0 3 1
A Loader.create(Record) 0 18 1
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.world.repository.implementation.sql;
21
22
import fr.arakne.utils.maps.serializer.CellData;
23
import fr.arakne.utils.value.Dimensions;
24
import fr.quatrevieux.araknemu.core.dbal.executor.QueryExecutor;
25
import fr.quatrevieux.araknemu.core.dbal.repository.Record;
26
import fr.quatrevieux.araknemu.core.dbal.repository.RepositoryException;
27
import fr.quatrevieux.araknemu.core.dbal.repository.RepositoryUtils;
28
import fr.quatrevieux.araknemu.data.transformer.Transformer;
29
import fr.quatrevieux.araknemu.data.value.Geolocation;
30
import fr.quatrevieux.araknemu.data.world.entity.environment.MapTemplate;
31
import fr.quatrevieux.araknemu.data.world.repository.environment.MapTemplateRepository;
32
import org.checkerframework.checker.index.qual.NonNegative;
33
34
import java.sql.ResultSet;
35
import java.sql.SQLException;
36
import java.util.Collection;
37
38
/**
39
 * Map repository implementation for SQL database
40
 */
41
final class SqlMapTemplateRepository implements MapTemplateRepository {
42
    private final QueryExecutor executor;
43
    private final RepositoryUtils<MapTemplate> utils;
44
    private final Transformer<CellData[]> cellsTransformer;
45
    private final Transformer<@NonNegative int[][]> fightPlacesTransformer;
46
47 1
    public SqlMapTemplateRepository(QueryExecutor executor, Transformer<CellData[]> cellsTransformer, Transformer<@NonNegative int[][]> fightPlacesTransformer) {
48 1
        this.executor = executor;
49 1
        this.cellsTransformer = cellsTransformer;
50 1
        this.fightPlacesTransformer = fightPlacesTransformer;
51
52 1
        utils = new RepositoryUtils<>(this.executor, new Loader());
53 1
    }
54
55
    @Override
56
    public void initialize() throws RepositoryException {
57
        try {
58
            // @todo normalize names
0 ignored issues
show
introduced by
Comment matches to-do format '(TODO:)|(@todo )'.
Loading history...
59 1
            executor.query(
60
                "CREATE TABLE maps(" +
61
                    "id INTEGER PRIMARY KEY," +
62
                    "date VARCHAR(12)," +
63
                    "width INTEGER," +
64
                    "height INTEGER," +
65
                    "key TEXT," +
66
                    "mapData TEXT," +
67
                    "places TEXT," +
68
                    "MAP_X INTEGER," +
69
                    "MAP_Y INTEGER," +
70
                    "SUBAREA_ID INTEGER," +
71
                    "INDOOR BOOLEAN" +
72
                ")"
73
            );
74
75 1
            executor.query("CREATE INDEX IDX_MAP_POS ON maps (MAP_X, MAP_Y)");
76
        } catch (SQLException e) {
77
            throw new RepositoryException(e);
78 1
        }
79 1
    }
80
81
    @Override
82
    public void destroy() throws RepositoryException {
83
        try {
84 1
            executor.query("DROP TABLE maps");
85
        } catch (SQLException e) {
86
            throw new RepositoryException(e);
87 1
        }
88 1
    }
89
90
    @Override
91
    public MapTemplate get(@NonNegative int id) {
92 1
        return utils.findOne(
93
            "SELECT * FROM maps WHERE id = ?",
94 1
            stmt -> stmt.setInt(1, id)
95
        );
96
    }
97
98
    @Override
99
    public MapTemplate get(MapTemplate entity) throws RepositoryException {
100 1
        return get(entity.id());
101
    }
102
103
    @Override
104
    public Collection<MapTemplate> byGeolocation(Geolocation geolocation) {
105 1
        return utils.findAll("SELECT * FROM maps WHERE MAP_X = ? AND MAP_Y = ?", stmt -> {
106 1
            stmt.setInt(1, geolocation.x());
107 1
            stmt.setInt(2, geolocation.y());
108 1
        });
109
    }
110
111
    @Override
112
    public boolean has(MapTemplate entity) throws RepositoryException {
113 1
        return utils.aggregate(
114
            "SELECT COUNT(*) FROM maps WHERE id = ?",
115 1
            stmt -> stmt.setInt(1, entity.id())
116
        ) > 0;
117
    }
118
119
    @Override
120
    public Collection<MapTemplate> all() throws RepositoryException {
121 1
        return utils.findAll("SELECT * FROM maps");
122
    }
123
124 1
    private class Loader implements RepositoryUtils.Loader<MapTemplate> {
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...
125
        @Override
126
        public MapTemplate create(Record record) throws SQLException {
127 1
            return new MapTemplate(
128 1
                record.getNonNegativeInt("id"),
129 1
                record.getString("date"),
130
                new Dimensions(
131 1
                    record.getPositiveInt("width"),
132 1
                    record.getPositiveInt("height")
133
                ),
134 1
                record.getString("key"),
135 1
                record.unserialize("mapData", cellsTransformer),
136 1
                record.unserialize("places", fightPlacesTransformer),
137
                new Geolocation(
138 1
                    record.getInt("MAP_X"),
139 1
                    record.getInt("MAP_Y")
140
                ),
141 1
                record.getInt("SUBAREA_ID"),
142 1
                record.getBoolean("INDOOR")
143
            );
144
        }
145
146
        @Override
147
        public MapTemplate fillKeys(MapTemplate entity, ResultSet keys) {
148
            throw new RepositoryException("Read-only entity");
149
        }
150
    }
151
}
152