2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.persistence.jdbc.internal.utils;
16 import java.net.URISyntaxException;
17 import java.util.ArrayList;
18 import java.util.List;
19 import java.util.Properties;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.core.persistence.FilterCriteria;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
30 * @author Helmut Lehmeyer - Initial contribution
33 public class StringUtilsExt {
34 private static final Logger LOGGER = LoggerFactory.getLogger(StringUtilsExt.class);
37 * Replaces multiple found words with the given Array contents
39 * @param str String for replacement
40 * @param separate A String or Array to be replaced
41 * @param separators Array will be merged to str
44 public static final String replaceArrayMerge(String str, String separate, Object[] separators) {
46 for (int i = 0; i < separators.length; i++) {
47 s = s.replaceFirst(separate, (String) separators[i]);
53 * @see #replaceArrayMerge(String str, String separate, Object[] separators)
55 public static final String replaceArrayMerge(String str, String[] separate, String[] separators) {
57 for (int i = 0; i < separators.length; i++) {
58 s = s.replaceFirst(separate[i], separators[i]);
64 * @see #parseJdbcURL(String url, Properties def)
66 public static Properties parseJdbcURL(String url) {
67 return parseJdbcURL(url, null);
71 * <b>JDBC-URI Examples:</b><br/>
72 * jdbc:dbShortcut:c:/dev/databaseName<br/>
73 * jdbc:dbShortcut:scheme:c:/dev/databaseName<br/>
74 * jdbc:dbShortcut:scheme:c:\\dev\\databaseName<br/>
75 * jdbc:dbShortcut:./databaseName<br/>
76 * jdbc:dbShortcut:/databaseName<br/>
77 * jdbc:dbShortcut:~/databaseName<br/>
78 * jdbc:dbShortcut:/path/databaseName.db<br/>
79 * jdbc:dbShortcut:./../../path/databaseName<br/>
80 * jdbc:dbShortcut:scheme:./path/../path/databaseName;param1=true;<br/>
81 * jdbc:dbShortcut://192.168.0.145:3306/databaseName?param1=false¶m2=true
85 * @param def Predefined Properties Object
86 * @return A merged Properties Object may contain:<br/>
87 * parseValid (mandatory)<br/>
96 public static Properties parseJdbcURL(String url, @Nullable Properties def) {
99 props = new Properties();
101 props = new Properties(def);
104 if (url.length() < 9) {
109 if (url.contains("\\")) {
110 url = url.replaceAll("\\\\", "/");
113 // replace first ; with ?
114 if (url.contains(";")) {
115 // replace first ; with ?
116 url = url.replaceFirst(";", "?");
117 // replace other ; with &
118 url = url.replaceAll(";", "&");
121 if (url.split(":").length < 3 || url.indexOf("/") == -1) {
122 LOGGER.error("parseJdbcURL: URI '{}' is not well formated, expected uri like 'jdbc:dbShortcut:/path'", url);
123 props.put("parseValid", "false");
127 String[] protAndDb = stringBeforeSubstr(url, ":", 1).split(":");
128 if (!"jdbc".equals(protAndDb[0])) {
129 LOGGER.error("parseJdbcURL: URI '{}' is not well formated, expected suffix 'jdbc' found '{}'", url,
131 props.put("parseValid", "false");
134 props.put("parseValid", "true");
135 props.put("dbShortcut", protAndDb[1]);
139 dbURI = new URI(stringAfterSubstr(url, ":", 1).replaceFirst(" ", ""));
140 if (dbURI.getScheme() != null) {
141 props.put("scheme", dbURI.getScheme());
142 dbURI = new URI(stringAfterSubstr(url, ":", 2).replaceFirst(" ", ""));
144 } catch (URISyntaxException e) {
145 LOGGER.error("parseJdbcURL: URI '{}' is not well formated.", url, e);
150 if (dbURI.getQuery() != null) {
151 String[] q = dbURI.getQuery().split("&");
152 for (int i = 0; i < q.length; i++) {
153 String[] t = q[i].split("=");
154 props.put(t[0], t[1]);
156 props.put("pathQuery", dbURI.getQuery());
160 if (dbURI.getPath() != null) {
161 String gp = dbURI.getPath();
163 if (gp.indexOf("/") <= 1) {
164 if (substrPos(gp, st).size() > 1) {
165 path = stringBeforeLastSubstr(gp, st) + st;
167 path = stringBeforeSubstr(gp, st) + st;
170 if (dbURI.getScheme() != null && dbURI.getScheme().length() == 1) {
171 path = dbURI.getScheme() + ":" + path;
173 props.put("serverPath", path);
175 if (dbURI.getPath() != null) {
176 props.put("databaseName", stringAfterLastSubstr(dbURI.getPath(), "/"));
178 if (dbURI.getPort() != -1) {
179 props.put("portNumber", dbURI.getPort() + "");
181 if (dbURI.getHost() != null) {
182 props.put("serverName", dbURI.getHost());
189 * Returns a String before the last occurrence of a substring
191 public static String stringBeforeLastSubstr(String s, String substr) {
192 List<Integer> a = substrPos(s, substr);
193 return s.substring(0, a.get(a.size() - 1));
197 * Returns a String after the last occurrence of a substring
199 public static String stringAfterLastSubstr(String s, String substr) {
200 List<Integer> a = substrPos(s, substr);
201 return s.substring(a.get(a.size() - 1) + 1);
205 * Returns a String after the first occurrence of a substring
207 public static String stringAfterSubstr(String s, String substr) {
208 return s.substring(s.indexOf(substr) + 1);
212 * Returns a String after the n occurrence of a substring
214 public static String stringAfterSubstr(String s, String substr, int n) {
215 return s.substring(substrPos(s, substr).get(n) + 1);
219 * Returns a String before the first occurrence of a substring
221 public static String stringBeforeSubstr(String s, String substr) {
222 return s.substring(0, s.indexOf(substr));
226 * Returns a String before the n occurrence of a substring.
228 public static String stringBeforeSubstr(String s, String substr, int n) {
229 return s.substring(0, substrPos(s, substr).get(n));
233 * Returns a list with indices of the occurrence of a substring.
235 public static List<Integer> substrPos(String s, String substr) {
236 return substrPos(s, substr, true);
240 * Returns a list with indices of the occurrence of a substring.
242 public static List<Integer> substrPos(String s, String substr, boolean ignoreCase) {
243 int substrLength = substr.length();
244 int strLength = s.length();
245 List<Integer> arr = new ArrayList<>();
247 for (int i = 0; i < strLength - substrLength + 1; i++) {
248 if (s.regionMatches(ignoreCase, i, substr, 0, substrLength)) {
258 * @see java.lang.Object#toString()
260 public static String filterToString(FilterCriteria filter) {
261 StringBuilder builder = new StringBuilder();
262 builder.append("FilterCriteria [itemName=");
263 builder.append(filter.getItemName());
264 builder.append(", beginDate=");
265 builder.append(filter.getBeginDate());
266 builder.append(", endDate=");
267 builder.append(filter.getEndDate());
268 builder.append(", pageNumber=");
269 builder.append(filter.getPageNumber());
270 builder.append(", pageSize=");
271 builder.append(filter.getPageSize());
272 builder.append(", operator=");
273 builder.append(filter.getOperator());
274 builder.append(", ordering=");
275 builder.append(filter.getOrdering());
276 builder.append(", state=");
277 builder.append(filter.getState());
279 return builder.toString();