diff --git a/bundles/org.openhab.core/src/main/java/org/eclipse/smarthome/core/util/UIDUtils.java b/bundles/org.openhab.core/src/main/java/org/eclipse/smarthome/core/util/UIDUtils.java new file mode 100644 index 00000000000..198969cbe16 --- /dev/null +++ b/bundles/org.openhab.core/src/main/java/org/eclipse/smarthome/core/util/UIDUtils.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2010-2019 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.smarthome.core.util; + +import java.nio.charset.StandardCharsets; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Utilities for UIDs. + * + * @author Markus Rathgeb - Initial contribution + */ +@NonNullByDefault +public class UIDUtils { + + /** + * Encodes a given string to an UID using only allowed characters. + * + *
+ * The generated UID can be given to the {@link #decode(String)} function and it will result into the given value. + * + * @param value the string that should be encoded to a valid UID + * @return a string that if a valid UID (with respect to the allowed characters) + */ + public static String encode(final String value) { + if (value.isEmpty()) { + return value; + } + + final byte[] in = value.getBytes(StandardCharsets.UTF_8); + final byte[] out = new byte[in.length * 3]; + + int opos = 0; + for (int ipos = 0; ipos < in.length; ++ipos, ++opos) { + final byte cur = in[ipos]; + if (cur >= '0' && cur <= '9' || cur >= 'A' && cur <= 'Z' || cur >= 'a' && cur <= 'z') { + out[opos] = cur; + } else { + out[opos++] = '_'; + final byte[] hex = HexUtils.byteToHex(cur); + out[opos++] = hex[0]; + out[opos] = hex[1]; + } + } + + return new String(out, 0, opos, StandardCharsets.UTF_8); + } + + /** + * Decodes an UID that has been generated by the {@link #encode(String)} function. + * + *
+ * This function should only be used for UIDs generated by the {@link #encode(String)} function. For every other UID
+ * the result is rather useless or could result into an {@link IllegalArgumentException}.
+ *
+ * @param value the UID to decode
+ * @return the decoded UID string
+ * @throws IllegalArgumentException if the given UID is not a valid encoded input
+ */
+ public static String decode(final String value) {
+ if (value.isEmpty()) {
+ return value;
+ }
+
+ final byte[] in = value.getBytes(StandardCharsets.UTF_8);
+ final byte[] out = new byte[in.length];
+
+ int opos = 0;
+ for (int ipos = 0; ipos < in.length; ++ipos, ++opos) {
+ final byte cur = in[ipos];
+ if (cur >= '0' && cur <= '9' || cur >= 'A' && cur <= 'Z' || cur >= 'a' && cur <= 'z') {
+ out[opos] = cur;
+ } else if (cur == '_') {
+ final byte curHigh = in[++ipos];
+ final byte curLow = in[++ipos];
+ out[opos] = HexUtils.hexToByte(curHigh, curLow);
+ } else {
+ throw new IllegalArgumentException("Invalid input");
+ }
+ }
+
+ return new String(out, 0, opos, StandardCharsets.UTF_8);
+ }
+
+}
diff --git a/bundles/org.openhab.core/src/test/java/org/eclipse/smarthome/core/common/UIDUtilsTest.java b/bundles/org.openhab.core/src/test/java/org/eclipse/smarthome/core/common/UIDUtilsTest.java
new file mode 100644
index 00000000000..16be87e1858
--- /dev/null
+++ b/bundles/org.openhab.core/src/test/java/org/eclipse/smarthome/core/common/UIDUtilsTest.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2010-2019 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.eclipse.smarthome.core.common;
+
+import java.util.function.Consumer;
+
+import org.eclipse.smarthome.core.util.UIDUtils;
+import org.hamcrest.core.IsEqual;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests for {@link AbstractUID}.
+ *
+ * @author Markus Rathgeb - Initial contribution
+ */
+public class UIDUtilsTest {
+
+ @Test
+ public void encodeDecode() {
+ Consumer