b5322d6ff3dcab8d323c19899eda14e3764fa201
[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     private final String dbName;
61     protected final String controllerId;
62     protected final String tableName;
63
64     public SqlDBReaderWriter(SqlDBClient dbService, Entity e, String dbSuffix, Class<T> clazz, String dbName,
65             String controllerId) {
66         this.dbService = dbService;
67         this.entity = e;
68         this.clazz = clazz;
69         this.dbName = dbName;
70         this.tableName = this.entity.getName() + dbSuffix;
71         this.controllerId = controllerId;
72     }
73
74     public long count(List<Filter> filter) throws SQLException {
75         String query;
76         if (filter == null || filter.isEmpty()) {
77             query = String.format("SELECT table_rows FROM `information_schema`.`tables` "
78                     + "WHERE `table_schema` = '%s' AND `table_name` = '%s'", this.dbName, this.tableName);
79         } else {
80             query = String.format("SELECT COUNT(`id`) FROM `%s` %s", this.tableName,
81                     SqlQuery.getWhereExpression(filter));
82         }
83         ResultSet data = this.dbService.read(query);
84         long cnt = 0;
85         if (data.next()) {
86             cnt = data.getLong(1);
87         }
88         return cnt;
89     }
90
91     public long count(List<Filter> list, String controllerId) throws SQLException {
92         if (list == null) {
93             list = new ArrayList<>();
94         }
95         Optional<Filter> cFilter =
96                 list.stream().filter(e -> SqlDBMapper.ODLID_DBCOL.equals(e.getProperty())).findFirst();
97         if (!cFilter.isEmpty()) {
98             list.remove(cFilter.get());
99         }
100         if (controllerId != null) {
101             list.add(
102                     new FilterBuilder().setProperty(SqlDBMapper.ODLID_DBCOL).setFiltervalue(this.controllerId).build());
103         }
104         return this.count(list);
105     }
106
107     public QueryResult<T> getData(EntityInput input) {
108         SelectQuery query = new SelectQuery(this.tableName, input, this.controllerId);
109         LOG.trace("query={}", query.toSql());
110         try {
111             ResultSet data = this.dbService.read(query.toSql());
112             List<T> mappedData = SqlDBMapper.read(data, clazz);
113             final Map<FilterKey, Filter> filter = input.getFilter();
114             long total = this.count(filter != null ? new ArrayList<>(filter.values()) : null, this.controllerId);
115             return new QueryResult<T>(mappedData, query.getPage(), query.getPageSize(), total);
116         } catch (SQLException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
117                 | InstantiationException | SecurityException | NoSuchMethodException | JsonProcessingException e) {
118             LOG.warn("problem reading data {}: ", this.entity, e);
119         }
120         return QueryResult.createEmpty();
121     }
122
123
124
125     public <S extends DataObject> String write(S object, String id) {
126         if (id == null) {
127             return this.writeWithoutId(object);
128         }
129         InsertQuery<S> query = new InsertQuery<S>(this.entity, object, this.controllerId);
130         query.setId(id);
131         boolean success = false;
132         try {
133             success = this.dbService.write(query.toSql());
134         } catch (SQLException e) {
135             LOG.warn("problem writing data into db: ", e);
136         }
137
138         return success ? id : null;
139     }
140
141     private <S extends DataObject> String writeWithoutId(S object) {
142
143         InsertQuery<S> query = new InsertQuery<S>(this.entity, object, this.controllerId);
144         try {
145             return this.dbService.writeAndReturnId(query.toSql());
146         } catch (SQLException e) {
147             LOG.warn("problem writing data into db: ", e);
148         }
149         return null;
150     }
151
152     public <S extends DataObject> String update(S object, String id) {
153         UpdateQuery<S> query = new UpdateQuery<S>(this.entity, object, this.controllerId);
154         query.setId(id);
155         String insertedId = null;
156         PreparedStatement stmt = null;
157         try {
158             Connection connection = this.dbService.getConnection();
159             stmt = connection.prepareStatement(query.toSql());
160             stmt.execute();
161
162             int affectedRows = stmt.getUpdateCount();
163             connection.close();
164             if (affectedRows > 0) {
165                 insertedId = id;
166             }
167         } catch (SQLException e) {
168             LOG.warn("problem writing data into db: ", e);
169         } finally {
170             if (stmt != null) {
171                 try {
172                     stmt.close();
173                 } catch (SQLException e) {
174                     LOG.warn("problem closing sql statement: ", e);
175                 }
176             }
177         }
178
179         return insertedId;
180     }
181
182     public <S extends DataObject> String updateOrInsert(S object, String id) {
183         UpsertQuery<S> query = new UpsertQuery<S>(this.entity, object, this.controllerId);
184         query.setId(id);
185         String insertedId = null;
186         LOG.trace("query={}", query.toSql());
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         } catch (SQLException e) {
199             LOG.warn("problem writing data into db: ", e);
200         } finally {
201             if (stmt != null) {
202                 try {
203                     stmt.close();
204                 } catch (SQLException e) {
205                     LOG.warn("problem closing sql statement: ", e);
206                 }
207             }
208         }
209         return insertedId;
210     }
211
212     public SqlDBReaderWriter<T> setWriteInterface(Class<? extends DataObject> writeInterfaceClazz) {
213         LOG.debug("Set write interface to {}", writeInterfaceClazz);
214         if (writeInterfaceClazz == null) {
215             throw new IllegalArgumentException("Null not allowed here.");
216         }
217
218         //      this.writeInterfaceClazz = writeInterfaceClazz;
219         return this;
220     }
221
222     public int remove(List<Filter> filters) {
223         DeleteQuery query = new DeleteQuery(this.entity, filters);
224         int affectedRows = 0;
225         PreparedStatement stmt = null;
226         try {
227             Connection connection = this.dbService.getConnection();
228             stmt = connection.prepareStatement(query.toSql());
229             stmt.execute();
230             affectedRows = stmt.getUpdateCount();
231             connection.close();
232         } catch (SQLException e) {
233             LOG.warn("problem execute delete query: ", e);
234         } finally {
235             if (stmt != null) {
236                 try {
237                     stmt.close();
238                 } catch (SQLException e) {
239                     LOG.warn("problem closing sql statement: ", e);
240                 }
241             }
242         }
243         return affectedRows;
244     }
245
246     public int remove(@Nullable String id) {
247         return this.remove(Arrays.asList(new FilterBuilder().setProperty("id").setFiltervalue(id).build()));
248     }
249
250     public <S extends DataObject> List<S> readAll(Class<S> clazz) {
251         SelectQuery query = new SelectQuery(this.tableName);
252         try {
253             ResultSet data = this.dbService.read(query.toSql());
254             List<S> mappedData = SqlDBMapper.read(data, clazz);
255             return mappedData;
256         } catch (SQLException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
257                 | InstantiationException | SecurityException | NoSuchMethodException | JsonProcessingException e) {
258             LOG.warn("problem reading all data{}: ", this.entity, e);
259         }
260         return null;
261     }
262
263     public List<String> readAll(String key) {
264         SelectQuery query = new SelectQuery(this.tableName, key, this.controllerId).groupBy(key);
265         try {
266             ResultSet data = this.dbService.read(query.toSql());
267             List<String> mappedData = SqlDBMapper.read(data, String.class, key);
268             return mappedData;
269         } catch (SQLException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
270                 | InstantiationException | SecurityException | NoSuchMethodException | JsonProcessingException e) {
271             LOG.warn("problem reading all data {} for key: ", this.entity, key, e);
272         }
273         return null;
274     }
275 }