2 * Copyright (c) 2010-2024 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 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 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/>
75 * jdbc:dbShortcut:c:/dev/databaseName<br/>
76 * jdbc:dbShortcut:scheme:c:/dev/databaseName<br/>
77 * jdbc:dbShortcut:scheme:c:\\dev\\databaseName<br/>
78 * jdbc:dbShortcut:./databaseName<br/>
79 * jdbc:dbShortcut:/databaseName<br/>
80 * jdbc:dbShortcut:~/databaseName<br/>
81 * jdbc:dbShortcut:/path/databaseName.db<br/>
82 * jdbc:dbShortcut:./../../path/databaseName<br/>
83 * jdbc:dbShortcut:scheme:./path/../path/databaseName;param1=true;<br/>
84 * jdbc:dbShortcut://192.168.0.145:3306/databaseName?param1=false¶m2=true
90 * @param def Predefined Properties Object
91 * @return A merged Properties Object may contain:<br/>
92 * parseValid (mandatory)<br/>
101 public static Properties parseJdbcURL(String url, @Nullable Properties def) {
104 props = new Properties();
106 props = new Properties(def);
109 if (url.length() < 9) {
114 if (url.contains("\\")) {
115 url = url.replaceAll("\\\\", "/");
118 // replace first ; with ?
119 if (url.contains(";")) {
120 // replace first ; with ?
121 url = url.replaceFirst(";", "?");
122 // replace other ; with &
123 url = url.replace(";", "&");
126 if (url.split(":").length < 3 || url.indexOf("/") == -1) {
127 LOGGER.error("parseJdbcURL: URI '{}' is not well formated, expected uri like 'jdbc:dbShortcut:/path'", url);
128 props.put("parseValid", "false");
132 String[] protAndDb = stringBeforeSubstr(url, ":", 1).split(":");
133 if (!"jdbc".equals(protAndDb[0])) {
134 LOGGER.error("parseJdbcURL: URI '{}' is not well formated, expected suffix 'jdbc' found '{}'", url,
136 props.put("parseValid", "false");
139 props.put("parseValid", "true");
140 props.put("dbShortcut", protAndDb[1]);
144 dbURI = new URI(stringAfterSubstr(url, ":", 1).replaceFirst(" ", ""));
145 if (dbURI.getScheme() != null) {
146 props.put("scheme", dbURI.getScheme());
147 dbURI = new URI(stringAfterSubstr(url, ":", 2).replaceFirst(" ", ""));
149 } catch (URISyntaxException e) {
150 LOGGER.error("parseJdbcURL: URI '{}' is not well formated.", url, e);
155 if (dbURI.getQuery() != null) {
156 String[] q = dbURI.getQuery().split("&");
157 for (int i = 0; i < q.length; i++) {
158 String[] t = q[i].split("=");
159 props.put(t[0], t[1]);
161 props.put("pathQuery", dbURI.getQuery());
165 if (dbURI.getPath() != null) {
166 String gp = dbURI.getPath();
168 if (gp.indexOf("/") <= 1) {
169 if (substrPos(gp, st).size() > 1) {
170 path = stringBeforeLastSubstr(gp, st) + st;
172 path = stringBeforeSubstr(gp, st) + st;
175 if (dbURI.getScheme() != null && dbURI.getScheme().length() == 1) {
176 path = dbURI.getScheme() + ":" + path;
178 props.put("serverPath", path);
180 if (dbURI.getPath() != null) {
181 props.put("databaseName", stringAfterLastSubstr(dbURI.getPath(), "/"));
183 if (dbURI.getPort() != -1) {
184 props.put("portNumber", dbURI.getPort() + "");
186 if (dbURI.getHost() != null) {
187 props.put("serverName", dbURI.getHost());
194 * Returns a String before the last occurrence of a substring
196 public static String stringBeforeLastSubstr(String s, String substr) {
197 List<Integer> a = substrPos(s, substr);
198 return s.substring(0, a.get(a.size() - 1));
202 * Returns a String after the last occurrence of a substring
204 public static String stringAfterLastSubstr(String s, String substr) {
205 List<Integer> a = substrPos(s, substr);
206 return s.substring(a.get(a.size() - 1) + 1);
210 * Returns a String after the first occurrence of a substring
212 public static String stringAfterSubstr(String s, String substr) {
213 return s.substring(s.indexOf(substr) + 1);
217 * Returns a String after the n occurrence of a substring
219 public static String stringAfterSubstr(String s, String substr, int n) {
220 return s.substring(substrPos(s, substr).get(n) + 1);
224 * Returns a String before the first occurrence of a substring
226 public static String stringBeforeSubstr(String s, String substr) {
227 return s.substring(0, s.indexOf(substr));
231 * Returns a String before the n occurrence of a substring.
233 public static String stringBeforeSubstr(String s, String substr, int n) {
234 return s.substring(0, substrPos(s, substr).get(n));
238 * Returns a list with indices of the occurrence of a substring.
240 public static List<Integer> substrPos(String s, String substr) {
241 return substrPos(s, substr, true);
245 * Returns a list with indices of the occurrence of a substring.
247 public static List<Integer> substrPos(String s, String substr, boolean ignoreCase) {
248 int substrLength = substr.length();
249 int strLength = s.length();
250 List<Integer> arr = new ArrayList<>();
252 for (int i = 0; i < strLength - substrLength + 1; i++) {
253 if (s.regionMatches(ignoreCase, i, substr, 0, substrLength)) {
263 * @see java.lang.Object#toString()
265 public static String filterToString(FilterCriteria filter) {
266 StringBuilder builder = new StringBuilder();
267 builder.append("FilterCriteria [itemName=");
268 builder.append(filter.getItemName());
269 builder.append(", beginDate=");
270 builder.append(filter.getBeginDate());
271 builder.append(", endDate=");
272 builder.append(filter.getEndDate());
273 builder.append(", pageNumber=");
274 builder.append(filter.getPageNumber());
275 builder.append(", pageSize=");
276 builder.append(filter.getPageSize());
277 builder.append(", operator=");
278 builder.append(filter.getOperator());
279 builder.append(", ordering=");
280 builder.append(filter.getOrdering());
281 builder.append(", state=");
282 builder.append(filter.getState());
284 return builder.toString();