2 * Copyright (c) 2010-2021 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.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) {
45 for (int i = 0; i < separators.length; i++) {
46 str = str.replaceFirst(separate, (String) separators[i]);
52 * @see #replaceArrayMerge(String str, String separate, Object[] separators)
54 public static final String replaceArrayMerge(String str, String[] separate, String[] separators) {
55 for (int i = 0; i < separators.length; i++) {
56 str = str.replaceFirst(separate[i], separators[i]);
62 * @see #parseJdbcURL(String url, Properties def)
64 public static Properties parseJdbcURL(String url) {
65 return parseJdbcURL(url, null);
69 * <b>JDBC-URI Examples:</b><br/>
70 * jdbc:dbShortcut:c:/dev/databaseName<br/>
71 * jdbc:dbShortcut:scheme:c:/dev/databaseName<br/>
72 * jdbc:dbShortcut:scheme:c:\\dev\\databaseName<br/>
73 * jdbc:dbShortcut:./databaseName<br/>
74 * jdbc:dbShortcut:/databaseName<br/>
75 * jdbc:dbShortcut:~/databaseName<br/>
76 * jdbc:dbShortcut:/path/databaseName.db<br/>
77 * jdbc:dbShortcut:./../../path/databaseName<br/>
78 * jdbc:dbShortcut:scheme:./path/../path/databaseName;param1=true;<br/>
79 * jdbc:dbShortcut://192.168.0.145:3306/databaseName?param1=false¶m2=true
83 * @param def Predefined Properties Object
84 * @return A merged Properties Object may contain:<br/>
85 * parseValid (mandatory)<br/>
94 public static Properties parseJdbcURL(String url, @Nullable Properties def) {
97 props = new Properties();
99 props = new Properties(def);
102 if (url == null || url.length() < 9) {
107 if (url.contains("\\")) {
108 url = url.replaceAll("\\\\", "/");
111 // replace first ; with ?
112 if (url.contains(";")) {
113 // replace first ; with ?
114 url = url.replaceFirst(";", "?");
115 // replace other ; with &
116 url = url.replaceAll(";", "&");
119 if (url.split(":").length < 3 || url.indexOf("/") == -1) {
120 LOGGER.error("parseJdbcURL: URI '{}' is not well formated, expected uri like 'jdbc:dbShortcut:/path'", url);
121 props.put("parseValid", "false");
125 String[] protAndDb = stringBeforeSubstr(url, ":", 1).split(":");
126 if (!"jdbc".equals(protAndDb[0])) {
127 LOGGER.error("parseJdbcURL: URI '{}' is not well formated, expected suffix 'jdbc' found '{}'", url,
129 props.put("parseValid", "false");
132 props.put("parseValid", "true");
133 props.put("dbShortcut", protAndDb[1]);
137 dbURI = new URI(stringAfterSubstr(url, ":", 1).replaceFirst(" ", ""));
138 if (dbURI.getScheme() != null) {
139 props.put("scheme", dbURI.getScheme());
140 dbURI = new URI(stringAfterSubstr(url, ":", 2).replaceFirst(" ", ""));
142 } catch (URISyntaxException e) {
143 LOGGER.error("parseJdbcURL: URI '{}' is not well formated.", url, e);
148 if (dbURI.getQuery() != null) {
149 String[] q = dbURI.getQuery().split("&");
150 for (int i = 0; i < q.length; i++) {
151 String[] t = q[i].split("=");
152 props.put(t[0], t[1]);
154 props.put("pathQuery", dbURI.getQuery());
158 if (dbURI.getPath() != null) {
159 String gp = dbURI.getPath();
161 if (gp.indexOf("/") <= 1) {
162 if (substrPos(gp, st).size() > 1) {
163 path = stringBeforeLastSubstr(gp, st) + st;
165 path = stringBeforeSubstr(gp, st) + st;
168 if (dbURI.getScheme() != null && dbURI.getScheme().length() == 1) {
169 path = dbURI.getScheme() + ":" + path;
171 props.put("serverPath", path);
173 if (dbURI.getPath() != null) {
174 props.put("databaseName", stringAfterLastSubstr(dbURI.getPath(), "/"));
176 if (dbURI.getPort() != -1) {
177 props.put("portNumber", dbURI.getPort() + "");
179 if (dbURI.getHost() != null) {
180 props.put("serverName", dbURI.getHost());
187 * Returns a String before the last occurrence of a substring
189 public static String stringBeforeLastSubstr(String s, String substr) {
190 List<Integer> a = substrPos(s, substr);
191 return s.substring(0, a.get(a.size() - 1));
195 * Returns a String after the last occurrence of a substring
197 public static String stringAfterLastSubstr(String s, String substr) {
198 List<Integer> a = substrPos(s, substr);
199 return s.substring(a.get(a.size() - 1) + 1);
203 * Returns a String after the first occurrence of a substring
205 public static String stringAfterSubstr(String s, String substr) {
206 return s.substring(s.indexOf(substr) + 1);
210 * Returns a String after the n occurrence of a substring
212 public static String stringAfterSubstr(String s, String substr, int n) {
213 return s.substring(substrPos(s, substr).get(n) + 1);
217 * Returns a String before the first occurrence of a substring
219 public static String stringBeforeSubstr(String s, String substr) {
220 return s.substring(0, s.indexOf(substr));
224 * Returns a String before the n occurrence of a substring.
226 public static String stringBeforeSubstr(String s, String substr, int n) {
227 return s.substring(0, substrPos(s, substr).get(n));
231 * Returns a list with indices of the occurrence of a substring.
233 public static List<Integer> substrPos(String s, String substr) {
234 return substrPos(s, substr, true);
238 * Returns a list with indices of the occurrence of a substring.
240 public static List<Integer> substrPos(String s, String substr, boolean ignoreCase) {
241 int substrLength = substr.length();
242 int strLength = s.length();
243 List<Integer> arr = new ArrayList<>();
245 for (int i = 0; i < strLength - substrLength + 1; i++) {
246 if (s.regionMatches(ignoreCase, i, substr, 0, substrLength)) {
256 * @see java.lang.Object#toString()
258 public static String filterToString(FilterCriteria filter) {
259 StringBuilder builder = new StringBuilder();
260 builder.append("FilterCriteria [itemName=");
261 builder.append(filter.getItemName());
262 builder.append(", beginDate=");
263 builder.append(filter.getBeginDate());
264 builder.append(", endDate=");
265 builder.append(filter.getEndDate());
266 builder.append(", pageNumber=");
267 builder.append(filter.getPageNumber());
268 builder.append(", pageSize=");
269 builder.append(filter.getPageSize());
270 builder.append(", operator=");
271 builder.append(filter.getOperator());
272 builder.append(", ordering=");
273 builder.append(filter.getOrdering());
274 builder.append(", state=");
275 builder.append(filter.getState());
277 return builder.toString();