2 * ============LICENSE_START=======================================================
3 * ONAP : ccsdk features
4 * ================================================================================
5 * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
22 package org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.query;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Calendar;
27 import java.util.Date;
28 import java.util.List;
29 import java.util.TimeZone;
30 import org.eclipse.jdt.annotation.Nullable;
31 import org.onap.ccsdk.features.sdnr.wt.common.database.data.DbFilter;
32 import org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.query.filters.DBFilterKeyValuePair;
33 import org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.query.filters.RangeSqlDBFilter;
34 import org.onap.ccsdk.features.sdnr.wt.dataprovider.database.sqldb.query.filters.RegexSqlDBFilter;
35 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.NetconfTimeStamp;
36 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.types.NetconfTimeStampImpl;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.entity.input.Filter;
39 public interface SqlQuery {
43 static final List<String> TIMESTAMPPROPERTYNAMES = Arrays.asList("timestamp", "time-stamp", "start", "end");
44 static final String MARIADB_TIMESTAMP_REPLACER = "0000-00-00 00:00:00.000";
45 static final String NETCONF_TIMESTAMP_REPLACER = "0000-00-00T00:00:00.000Z";
46 static final String MARIADB_TIMESTAMP_REPLACER_MIN = "0000-00-00 00:00:00";
47 static final int MARIADB_TIMESTAMP_REPLACER_MIN_LENGTH = MARIADB_TIMESTAMP_REPLACER_MIN.length();
48 static final int MARIADB_TIMESTAMP_REPLACER_MAX_LENGTH = MARIADB_TIMESTAMP_REPLACER.length();
50 public static String getWhereExpression(List<Filter> filters) {
51 if (filters == null) {
54 StringBuilder sb = new StringBuilder();
55 if (filters.size() > 0) {
57 sb.append(" WHERE (" + getFilterExpression(filters.get(0)) + ")");
58 for (int i = 1; i < filters.size(); i++) {
59 sb.append(" AND (" + getFilterExpression(filters.get(i)) + ")");
65 public static String getFilterExpression(Filter filter) {
66 String property = filter.getProperty();
67 List<String> values = collectValues(filter.getFiltervalue(), filter.getFiltervalues());
68 if (values.size() == 1) {
69 return getFilterExpression(property, values.get(0));
70 } else if (values.size() > 1) {
71 StringBuilder sb = new StringBuilder();
72 sb.append(getFilterExpression(property, values.get(0)));
73 for (int i = 1; i < values.size(); i++) {
75 sb.append(getFilterExpression(property, values.get(i)));
82 public static String getFilterExpression(String property, String value) {
83 String filter = null;;
84 if (DbFilter.hasSearchParams(value)) {
85 if (TIMESTAMPPROPERTYNAMES.contains(property.toLowerCase())) {
86 if (DbFilter.isComparisonValid(value)) {
87 filter = getComparisonFilter(property, value, true);
89 filter = fromTimestampSearchFilter(property, value);
95 return new RegexSqlDBFilter(property, value).getFilterExpression();
96 } else if (DbFilter.isComparisonValid(value)) {
97 filter = getComparisonFilter(property, value, TIMESTAMPPROPERTYNAMES.contains(property.toLowerCase()));
102 return new DBFilterKeyValuePair(property, value).getFilterExpression();
105 static List<String> collectValues(String filtervalue, List<String> filtervalues) {
106 if (filtervalues == null) {
107 return Arrays.asList(filtervalue);
109 List<String> values = new ArrayList<>();
110 if (filtervalue != null) {
111 values.add(filtervalue);
113 values.addAll(filtervalues);
117 private static String getComparisonFilter(String property, String filtervalue, boolean asTimeStamp) {
118 filtervalue = filtervalue.trim();
119 String comparator = null;
121 if (filtervalue.startsWith(">=")) {
123 filtervalue = filtervalue.substring(2).trim();
125 filtervalue = netconfToMariaDBTimestamp(fillTimeStamp(
126 filtervalue.endsWith("*") ? filtervalue : (filtervalue + "*"), MARIADB_TIMESTAMP_REPLACER));
128 } else if (filtervalue.startsWith(">")) {
130 filtervalue = filtervalue.substring(1).trim();
132 if (isFullTimestamp(filtervalue)) {
133 filtervalue = netconfToMariaDBTimestamp(filtervalue);
136 filtervalue = netconfToMariaDBTimestamp(
137 fillTimeStamp(filtervalue.endsWith("*") ? filtervalue : (filtervalue + "*"),
138 NETCONF_TIMESTAMP_REPLACER, true));
141 } else if (filtervalue.startsWith("<=")) {
143 filtervalue = filtervalue.substring(2).trim();
145 if (isFullTimestamp(filtervalue)) {
146 filtervalue = netconfToMariaDBTimestamp(filtervalue);
149 filtervalue = netconfToMariaDBTimestamp(
150 fillTimeStamp(filtervalue.endsWith("*") ? filtervalue : (filtervalue + "*"),
151 NETCONF_TIMESTAMP_REPLACER, true));
154 } else if (filtervalue.startsWith("<")) {
156 filtervalue = filtervalue.substring(1).trim();
158 filtervalue = netconfToMariaDBTimestamp(fillTimeStamp(
159 filtervalue.endsWith("*") ? filtervalue : (filtervalue + "*"), MARIADB_TIMESTAMP_REPLACER));
165 return new RangeSqlDBFilter(property, value, comparator).getFilterExpression();
168 static boolean isFullTimestamp(String v) {
169 return v.length() >= MARIADB_TIMESTAMP_REPLACER_MIN_LENGTH;
173 * Convert timestamp beginning filter expression like 2017* to a full qualified timestamp like '2017-01-01
176 * @param value filter input value
177 * @return fully qualified timestamp
179 private static String fillTimeStamp(String value) {
180 return fillTimeStamp(value, NETCONF_TIMESTAMP_REPLACER);
183 private static String fillTimeStamp(String value, String replacer) {
184 return fillTimeStamp(value, replacer, false);
187 private static String fillTimeStamp(String value, String replacer, boolean useUpperEnd) {
188 int idx = value.lastIndexOf("*");
190 if (idx > replacer.length()) {
191 s = value.substring(0, replacer.length());
193 s = value.substring(0, idx) + replacer.substring(idx);
195 //if month is zero => set to 1
196 if (Integer.parseInt(s.substring(5, 7)) == 0) {
197 s = s.substring(0, 5) + "01-" + s.substring(8);
199 //if day is zero => set to 1
200 if (Integer.parseInt(s.substring(8, 10)) == 0) {
201 s = s.substring(0, 8) + "01" + s.substring(10);
204 s = getTimestampUpperLimit(s, idx);
210 * convert timestamp with ending placeholder in filter to elasticsearch filter e.g. 2017* => gte: 2017-01-01
211 * 00:00:00, lt:2018-01-01 00:00:00Z
213 * 201* => 2010-01... 2020 .. 2018-* => 2018-01... <=> 2019-01
216 private static @Nullable String fromTimestampSearchFilter(String property, String value) {
217 if (!value.endsWith("*")) {
220 int idx = value.lastIndexOf("*");
221 String lowerEnd = fillTimeStamp(value);
222 String upperEnd = getTimestampUpperLimit(fillTimeStamp(value, "0000-00-00T00:00:00.0Z"), idx);
223 return RangeSqlDBFilter.between(property, netconfToMariaDBTimestamp(lowerEnd), true,
224 netconfToMariaDBTimestamp(upperEnd), false);
227 private static String netconfToMariaDBTimestamp(String ts) {
228 String v = ts.replace("T", " ").replace("Z", "");
229 return v.length() > MARIADB_TIMESTAMP_REPLACER_MAX_LENGTH
230 ? v.substring(0, MARIADB_TIMESTAMP_REPLACER_MAX_LENGTH)
234 private static String getTimestampUpperLimit(String lowerEnd, int idx) {
236 String upperEnd = null;
237 NetconfTimeStamp converter = NetconfTimeStampImpl.getConverter();
240 dt = converter.getDateFromNetconf(lowerEnd);
241 } catch (Exception e) {
247 // property.substring(0,idx)+REPLACE.substring(idx+1);
248 Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
253 c.set(Calendar.YEAR, c.get(Calendar.YEAR) + 1000);
254 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
257 c.set(Calendar.YEAR, c.get(Calendar.YEAR) + 100);
258 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
261 c.set(Calendar.YEAR, c.get(Calendar.YEAR) + 10);
262 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
266 c.set(Calendar.YEAR, c.get(Calendar.YEAR) + 1);
267 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
269 case 6: // switch 10 months (2000-0* or 2000-1*)
270 tmpvalue = c.get(Calendar.MONTH);
272 c.set(Calendar.MONTH, 9);
274 c.set(Calendar.YEAR, c.get(Calendar.YEAR) + 1);
275 c.set(Calendar.MONTH, 0);
277 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
280 case 7: // switch one month (2018-01* or 2018-01-*)
282 c.add(Calendar.MONTH, 1);
283 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
285 case 9: // (2018-01-0*)
286 tmpvalue = c.get(Calendar.DAY_OF_MONTH);
288 c.set(Calendar.DAY_OF_MONTH, 10);
289 } else if (tmpvalue == 10) {
290 c.set(Calendar.DAY_OF_MONTH, 20);
291 } else if (tmpvalue == 20) {
292 if (c.getActualMaximum(Calendar.DAY_OF_MONTH) < 30) {
293 c.set(Calendar.DAY_OF_MONTH, 1);
294 c.add(Calendar.MONTH, 1);
296 c.set(Calendar.DAY_OF_MONTH, 30);
298 } else if (tmpvalue == 30) {
299 c.set(Calendar.DAY_OF_MONTH, 1);
300 c.add(Calendar.MONTH, 1);
304 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
306 case 10: // (2018-01-01*)
307 case 11: // (2018-01-01T*)
308 c.add(Calendar.DAY_OF_MONTH, 1);
309 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
311 case 12: // (2018-01-01T1*)
312 tmpvalue = c.get(Calendar.HOUR_OF_DAY);
313 if (tmpvalue == 20) {
314 c.set(Calendar.HOUR_OF_DAY, 0);
315 c.add(Calendar.DAY_OF_MONTH, 1);
317 c.add(Calendar.HOUR_OF_DAY, 10);
319 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
321 case 13: // (2018-01-01T11*)
322 case 14: // (2018-01-01T11-*)
323 c.add(Calendar.HOUR_OF_DAY, 1);
324 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
326 case 15: // (2018-01-01T11-3*)
327 c.add(Calendar.MINUTE, 10);
328 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
330 case 16: // (2018-01-01T11-32*)
331 case 17: // (2018-01-01T11-32-*)
332 c.add(Calendar.MINUTE, 1);
333 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
335 case 18: // (2018-01-01T11-32-1*)
336 c.add(Calendar.SECOND, 10);
337 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());
339 case 19: // (2018-01-01T11-32-11*)
340 case 20: // (2018-01-01T11-32-11.*)
341 c.add(Calendar.SECOND, 1);
342 upperEnd = converter.getTimeStampAsNetconfString(c.getTime());