56e965c9fba39847d2940f4c4a29a740cf82f83f
[ccsdk/features.git] / sdnr / wt / data-provider / dblib / src / main / java / org / onap / ccsdk / features / sdnr / wt / dataprovider / database / sqldb / database / SqlDBReaderWriter.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : ccsdk features
4  * ================================================================================
5  * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
6  * All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  *
21  */
22 package org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.database;
23
24 import com.fasterxml.jackson.core.JsonProcessingException;
25 import java.lang.reflect.InvocationTargetException;
26 import java.sql.Connection;
27 import java.sql.PreparedStatement;
28 import java.sql.ResultSet;
29 import java.sql.SQLException;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Optional;
35 import org.eclipse.jdt.annotation.Nullable;
36 import org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.SqlDBClient;
37 import org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.data.rpctypehelper.QueryResult;
38 import org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.query.DeleteQuery;
39 import org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.query.InsertQuery;
40 import org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.query.SelectQuery;
41 import org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.query.SqlQuery;
42 import org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.query.UpdateQuery;
43 import org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.query.UpsertQuery;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.Entity;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.EntityInput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.entity.input.Filter;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.entity.input.FilterBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.entity.input.FilterKey;
49 import org.opendaylight.yangtools.yang.binding.DataObject;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 public class SqlDBReaderWriter<T extends DataObject> {
54
55     private static final Logger LOG = LoggerFactory.getLogger(SqlDBReaderWriter.class);
56
57     protected final Entity entity;
58     private final Class<T> clazz;
59     protected final SqlDBClient dbService;
60     protected final String controllerId;
61     protected final String tableName;
62     private final boolean ignoreControllerId;
63
64     public SqlDBReaderWriter(SqlDBClient dbService, Entity e, String dbSuffix, Class<T> clazz,
65             String controllerId) {
66         this(dbService, e, dbSuffix, clazz, controllerId, false);
67     }
68
69     public SqlDBReaderWriter(SqlDBClient dbService, Entity e, String dbSuffix, Class<T> clazz,
70             String controllerId, boolean ignoreControllerId) {
71         this.dbService = dbService;
72         this.entity = e;
73         this.clazz = clazz;
74         this.tableName = this.entity.getName() + dbSuffix;
75         this.controllerId = controllerId;
76         this.ignoreControllerId = ignoreControllerId;
77     }
78
79     public long count(List<Filter> filter) throws SQLException {
80         String query;
81         if (filter == null || filter.isEmpty()) {
82             //            query = String.format("SELECT table_rows FROM `information_schema`.`tables` "
83             //                    + "WHERE `table_schema` = '%s' AND `table_name` = '%s'", this.dbName, this.tableName);
84             query = String.format("SELECT COUNT(`id`) FROM `%s`", this.tableName);
85         } else {
86             query = String.format("SELECT COUNT(`id`) FROM `%s` %s", this.tableName,
87                     SqlQuery.getWhereExpression(filter));
88         }
89         ResultSet data = this.dbService.read(query);
90         if(data==null) {
91             return 0;
92         }
93         long cnt = 0;
94         if (data.next()) {
95             cnt = data.getLong(1);
96         }
97         try {
98             data.close();
99         } catch (SQLException ignore) {
100         }
101         return cnt;
102     }
103
104     public long count(List<Filter> list, String controllerId) throws SQLException {
105         if (list == null) {
106             list = new ArrayList<>();
107         }
108         Optional<Filter> cFilter =
109                 list.stream().filter(e -> SqlDBMapper.ODLID_DBCOL.equals(e.getProperty())).findFirst();
110         if (!cFilter.isEmpty()) {
111             list.remove(cFilter.get());
112         }
113         if (controllerId != null) {
114             list.add(
115                     new FilterBuilder().setProperty(SqlDBMapper.ODLID_DBCOL).setFiltervalue(this.controllerId).build());
116         }
117         return this.count(list);
118     }
119
120     public QueryResult<T> getData(EntityInput input) {
121         SelectQuery query = new SelectQuery(this.tableName, input, this.controllerId);
122         if (LOG.isTraceEnabled()) {
123             LOG.trace("query={}", query.toSql());
124         }
125         try {
126             ResultSet data = this.dbService.read(query.toSql());
127             List<T> mappedData = SqlDBMapper.read(data, clazz);
128             final Map<FilterKey, Filter> filter = input.getFilter();
129             try {
130                 if(data!=null) {
131                     data.close();
132                 }
133             } catch (SQLException ignore) {
134             }
135             long total = this.count(filter != null ? new ArrayList<>(filter.values()) : null, this.controllerId);
136             return new QueryResult<T>(mappedData, query.getPage(), query.getPageSize(), total);
137         } catch (SQLException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
138                 | InstantiationException | SecurityException | NoSuchMethodException | JsonProcessingException e) {
139             LOG.warn("problem reading data {}: ", this.entity, e);
140         }
141         return QueryResult.createEmpty();
142     }
143
144
145
146     public <S extends DataObject> String write(S object, String id) {
147         if (id == null) {
148             return this.writeWithoutId(object);
149         }
150         InsertQuery<S> query = new InsertQuery<S>(this.entity, object, this.controllerId, this.ignoreControllerId);
151         query.setId(id);
152         if (LOG.isTraceEnabled()) {
153             LOG.trace("query={}", query.toSql());
154         }
155         boolean success = false;
156         try {
157             success = this.dbService.write(query.toSql());
158         } catch (SQLException e) {
159             LOG.warn("problem writing data into db: ", e);
160         }
161
162         return success ? id : null;
163     }
164
165     private <S extends DataObject> String writeWithoutId(S object) {
166
167         InsertQuery<S> query =
168                 new InsertQuery<S>(this.entity, object, this.controllerId, this.ignoreControllerId, true);
169         if (LOG.isTraceEnabled()) {
170             LOG.trace("query={}", query.toSql());
171         }
172         try {
173             return this.dbService.writeAndReturnId(query.toSql());
174         } catch (SQLException e) {
175             LOG.warn("problem writing data into db: ", e);
176         }
177         return null;
178     }
179
180     public <S extends DataObject> String update(S object, String id) {
181         UpdateQuery<S> query = new UpdateQuery<S>(this.entity, object, this.controllerId, this.ignoreControllerId, true);
182         query.setId(id);
183         if (LOG.isTraceEnabled()) {
184             LOG.trace("query={}", query.toSql());
185         }
186         String insertedId = null;
187         PreparedStatement stmt = null;
188         try {
189             Connection connection = this.dbService.getConnection();
190             stmt = connection.prepareStatement(query.toSql());
191             stmt.execute();
192
193             int affectedRows = stmt.getUpdateCount();
194             connection.close();
195             if (affectedRows > 0) {
196                 insertedId = id;
197             }
198             if (LOG.isTraceEnabled()) {
199                 LOG.trace("insertedid={}", insertedId);
200             }
201         } catch (SQLException e) {
202             LOG.warn("problem writing data into db: ", e);
203         } finally {
204             if (stmt != null) {
205                 try {
206                     stmt.close();
207                 } catch (SQLException e) {
208                     LOG.warn("problem closing sql statement: ", e);
209                 }
210             }
211         }
212
213         return insertedId;
214     }
215
216     public <S extends DataObject> String updateOrInsert(S object, String id) {
217         UpsertQuery<S> query = new UpsertQuery<S>(this.entity, object, this.controllerId, this.ignoreControllerId, true);
218         query.setId(id);
219         String insertedId = null;
220         if (LOG.isTraceEnabled()) {
221             LOG.trace("query={}", query.toSql());
222         }
223         PreparedStatement stmt = null;
224         try {
225             Connection connection = this.dbService.getConnection();
226             stmt = connection.prepareStatement(query.toSql());
227             stmt.execute();
228
229             int affectedRows = stmt.getUpdateCount();
230             connection.close();
231             if (affectedRows > 0) {
232                 insertedId = id;
233             }
234         } catch (SQLException e) {
235             LOG.warn("problem writing data into db: ", e);
236         } finally {
237             if (stmt != null) {
238                 try {
239                     stmt.close();
240                 } catch (SQLException e) {
241                     LOG.warn("problem closing sql statement: ", e);
242                 }
243             }
244         }
245         return insertedId;
246     }
247
248     public SqlDBReaderWriter<T> setWriteInterface(Class<? extends DataObject> writeInterfaceClazz) {
249         LOG.debug("Set write interface to {}", writeInterfaceClazz);
250         if (writeInterfaceClazz == null) {
251             throw new IllegalArgumentException("Null not allowed here.");
252         }
253
254         //      this.writeInterfaceClazz = writeInterfaceClazz;
255         return this;
256     }
257
258     public int remove(List<Filter> filters) {
259         DeleteQuery query = new DeleteQuery(this.entity, filters);
260         if (LOG.isTraceEnabled()) {
261             LOG.trace("query={}", query.toSql());
262         }
263         int affectedRows = 0;
264         PreparedStatement stmt = null;
265         try {
266             Connection connection = this.dbService.getConnection();
267             stmt = connection.prepareStatement(query.toSql());
268             stmt.execute();
269             affectedRows = stmt.getUpdateCount();
270             connection.close();
271         } catch (SQLException e) {
272             LOG.warn("problem execute delete query: ", e);
273         } finally {
274             if (stmt != null) {
275                 try {
276                     stmt.close();
277                 } catch (SQLException e) {
278                     LOG.warn("problem closing sql statement: ", e);
279                 }
280             }
281         }
282         return affectedRows;
283     }
284
285     public int remove(@Nullable String id) {
286         return this.remove(Arrays.asList(new FilterBuilder().setProperty("id").setFiltervalue(id).build()));
287     }
288
289     public <S extends DataObject> List<S> readAll(Class<S> clazz) {
290         SelectQuery query = new SelectQuery(this.tableName);
291         if (LOG.isTraceEnabled()) {
292             LOG.trace("query={}", query.toSql());
293         }
294         try {
295             ResultSet data = this.dbService.read(query.toSql());
296             List<S> mappedData = SqlDBMapper.read(data, clazz);
297             try {
298                 data.close();
299             } catch (SQLException ignore) {
300             }
301             return mappedData;
302         } catch (SQLException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
303                 | InstantiationException | SecurityException | NoSuchMethodException | JsonProcessingException e) {
304             LOG.warn("problem reading all data{}: ", this.entity, e);
305         }
306         return null;
307     }
308
309     public List<String> readAll(String key) {
310         SelectQuery query = new SelectQuery(this.tableName, key, this.controllerId).groupBy(key);
311         if (LOG.isTraceEnabled()) {
312             LOG.trace("query={}", query.toSql());
313         }
314         try {
315             ResultSet data = this.dbService.read(query.toSql());
316             List<String> mappedData = SqlDBMapper.read(data, String.class, key);
317             try {
318                 data.close();
319             } catch (SQLException ignore) {
320             }
321             return mappedData;
322         } catch (SQLException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
323                 | InstantiationException | SecurityException | NoSuchMethodException | JsonProcessingException e) {
324             LOG.warn("problem reading all data {} for key: ", this.entity, key, e);
325         }
326         return null;
327     }
328
329     public T read(String id) {
330         SelectQuery query =
331                 new SelectQuery(this.tableName, this.controllerId).addFilter(SqlDBMapper.ID_DBCOL, id);
332         if (LOG.isTraceEnabled()) {
333             LOG.trace("query={}", query.toSql());
334         }
335         T item = null;
336         try {
337             ResultSet data = this.dbService.read(query.toSql());
338             List<T> mappedData = SqlDBMapper.read(data, clazz);
339             item = mappedData.size()>0? mappedData.get(0): null;
340         } catch (SQLException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
341                 | InstantiationException | SecurityException | NoSuchMethodException | JsonProcessingException e) {
342             LOG.warn("problem reading data {}: ", this.entity, e);
343         }
344         return item;
345     }
346 }