Browse Source

TBEL: added padStart, padEnd, parseByteToBinaryArray, parseBytesToBinaryArray, parseLongToBinaryArray (#11323)

* tbel: added String.prototype.padStart() and String.prototype.padEnd() ;

* tbel: added binary String format

* tbel: added parseByteToBinaryArray, parseBytesToBinaryArray, parseLongToBinaryArray
pull/11340/head
Kulikov 2 years ago
committed by GitHub
parent
commit
ea235b7769
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 94
      common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java
  2. 135
      common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java

94
common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java

@ -63,6 +63,7 @@ public class TbUtils {
private static final int HEX_LEN_LONG_MAX = 16;
private static final int BYTES_LEN_INT_MAX = 4;
private static final int BYTES_LEN_LONG_MAX = 8;
private static final int BIN_LEN_MAX = 8;
private static final LinkedHashMap<String, String> mdnEncodingReplacements = new LinkedHashMap<>();
@ -326,7 +327,28 @@ public class TbUtils {
String.class)));
parserConfig.addImport("byteArrayToExecutionArrayList", new MethodStub(TbUtils.class.getMethod("byteArrayToExecutionArrayList",
ExecutionContext.class, byte[].class)));
parserConfig.addImport("padStart", new MethodStub(TbUtils.class.getMethod("padStart",
String.class, int.class, char.class)));
parserConfig.addImport("padEnd", new MethodStub(TbUtils.class.getMethod("padEnd",
String.class, int.class, char.class)));
parserConfig.addImport("parseByteToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseByteToBinaryArray",
byte.class)));
parserConfig.addImport("parseByteToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseByteToBinaryArray",
byte.class, int.class)));
parserConfig.addImport("parseBytesToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseBytesToBinaryArray",
List.class)));
parserConfig.addImport("parseBytesToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseBytesToBinaryArray",
List.class, int.class)));
parserConfig.addImport("parseBytesToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseBytesToBinaryArray",
byte[].class)));
parserConfig.addImport("parseBytesToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseBytesToBinaryArray",
byte[].class)));
parserConfig.addImport("parseBytesToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseBytesToBinaryArray",
byte[].class, int.class)));
parserConfig.addImport("parseLongToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseLongToBinaryArray",
long.class)));
parserConfig.addImport("parseLongToBinaryArray", new MethodStub(TbUtils.class.getMethod("parseLongToBinaryArray",
long.class, int.class)));
}
public static String btoa(String input) {
@ -629,6 +651,9 @@ public class TbUtils {
public static ExecutionArrayList<Byte> hexToBytes(ExecutionContext ctx, String value) {
String hex = prepareNumberString(value, true);
if (hex == null) {
throw new IllegalArgumentException("Hex string must be not empty!");
}
int len = hex.length();
if (len % 2 > 0) {
throw new IllegalArgumentException("Hex string must be even-length.");
@ -709,7 +734,7 @@ public class TbUtils {
return Long.toString(number, radix);
}
return switch (radix) {
case MIN_RADIX -> Long.toBinaryString(number);
case MIN_RADIX -> formatBinary(Long.toBinaryString(number));
case OCTAL_RADIX -> Long.toOctalString(number);
case DEC_RADIX -> Long.toString(number);
case HEX_RADIX -> prepareNumberHexString(number, bigEndian, pref, -1, -1);
@ -865,7 +890,7 @@ public class TbUtils {
}
public static long parseBytesToLong(byte[] data, int offset) {
return parseBytesToLong(data, offset, BYTES_LEN_LONG_MAX);
return parseBytesToLong(data, offset, validateLength(data.length, offset, BYTES_LEN_LONG_MAX));
}
public static long parseBytesToLong(byte[] data, int offset, int length) {
@ -1244,6 +1269,61 @@ public class TbUtils {
return list;
}
public static String padStart(String str, int targetLength, char padString) {
while (str.length() < targetLength) {
str = padString + str;
}
return str;
}
public static String padEnd(String str, int targetLength, char padString) {
while (str.length() < targetLength) {
str = str + padString;
}
return str;
}
public static int[] parseByteToBinaryArray(byte byteValue) {
return parseByteToBinaryArray(byteValue, BIN_LEN_MAX);
}
public static int[] parseByteToBinaryArray(byte byteValue, int binLength) {
int[] bins = new int[binLength];
for (int i = 0; i < binLength; i++) {
bins[i] = (byteValue & (1 << i)) >> i;
}
return bins;
}
public static int[] parseBytesToBinaryArray(List listValue) {
return parseBytesToBinaryArray(listValue, listValue.size() * BIN_LEN_MAX);
}
public static int[] parseBytesToBinaryArray(List listValue, int binLength) {
return parseBytesToBinaryArray(Bytes.toArray(listValue), binLength);
}
public static int[] parseBytesToBinaryArray(byte[] bytesValue) {
return parseLongToBinaryArray(parseBytesToLong(bytesValue), bytesValue.length * BIN_LEN_MAX);
}
public static int[] parseBytesToBinaryArray(byte[] bytesValue, int binLength) {
return parseLongToBinaryArray(parseBytesToLong(bytesValue), binLength);
}
public static int[] parseLongToBinaryArray(long longValue) {
return parseLongToBinaryArray(longValue, BYTES_LEN_LONG_MAX * BIN_LEN_MAX);
}
public static int[] parseLongToBinaryArray(long longValue, int binsLength) {
int len = Math.min(binsLength, BYTES_LEN_LONG_MAX * BIN_LEN_MAX);
int[] bins = new int[len];
for (int i = 0; i < len; i++) {
bins[i] = (int) ((longValue & (1 << i)) >> i);
}
return bins;
}
private static byte isValidIntegerToByte(Integer val) {
if (val > 255 || val < -128) {
throw new NumberFormatException("The value '" + val + "' could not be correctly converted to a byte. " +
@ -1288,5 +1368,13 @@ public class TbUtils {
private static int validateLength(int dataLength, int offset, int bytesLenMax) {
return (dataLength < offset) ? dataLength : Math.min((dataLength - offset), bytesLenMax);
}
private static String formatBinary(String binaryString) {
int format = binaryString.length() < 8 ? 8 :
binaryString.length() < 16 ? 16 :
binaryString.length() < 32 ? 32 :
binaryString.length() < 64 ? 64 : 0;
return format == 0 ? binaryString : String.format("%" + format + "s", binaryString).replace(' ', '0');
}
}

135
common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java

@ -226,11 +226,11 @@ public class TbUtilsTest {
Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt("0xFG"));
Assertions.assertEquals(java.util.Optional.of(102).get(), TbUtils.parseInt("1100110", 2));
Assertions.assertEquals(java.util.Optional.of(-102).get(), TbUtils.parseInt("1111111111111111111111111111111111111111111111111111111110011010", 2));
Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt("1100210", 2));
Assertions.assertEquals(java.util.Optional.of(13158).get(), TbUtils.parseInt("11001101100110", 2));
Assertions.assertEquals(java.util.Optional.of(-13158).get(), TbUtils.parseInt("1111111111111111111111111111111111111111111111111100110010011010", 2));
Assertions.assertEquals(java.util.Optional.of(102).get(), TbUtils.parseInt("1100110", MIN_RADIX));
Assertions.assertEquals(java.util.Optional.of(-102).get(), TbUtils.parseInt("1111111111111111111111111111111111111111111111111111111110011010", MIN_RADIX));
Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseInt("1100210", MIN_RADIX));
Assertions.assertEquals(java.util.Optional.of(13158).get(), TbUtils.parseInt("11001101100110", MIN_RADIX));
Assertions.assertEquals(java.util.Optional.of(-13158).get(), TbUtils.parseInt("1111111111111111111111111111111111111111111111111100110010011010", MIN_RADIX));
Assertions.assertEquals(java.util.Optional.of(63).get(), TbUtils.parseInt("77", 8));
@ -397,9 +397,9 @@ public class TbUtilsTest {
Assertions.assertEquals(java.util.Optional.of(4294967295L).get(), TbUtils.parseLong("FFFFFFFF"));
Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseLong("0xFGFFFFFF"));
Assertions.assertEquals(java.util.Optional.of(13158L).get(), TbUtils.parseLong("11001101100110", 2));
Assertions.assertEquals(java.util.Optional.of(-13158L).get(), TbUtils.parseLong("1111111111111111111111111111111111111111111111111100110010011010", 2));
Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseLong("11001101100210", 2));
Assertions.assertEquals(java.util.Optional.of(13158L).get(), TbUtils.parseLong("11001101100110", MIN_RADIX));
Assertions.assertEquals(java.util.Optional.of(-13158L).get(), TbUtils.parseLong("1111111111111111111111111111111111111111111111111100110010011010", MIN_RADIX));
Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseLong("11001101100210", MIN_RADIX));
Assertions.assertEquals(java.util.Optional.of(9223372036854775807L).get(), TbUtils.parseLong("777777777777777777777", 8));
Assertions.assertThrows(NumberFormatException.class, () -> TbUtils.parseLong("1787", 8));
@ -720,9 +720,13 @@ public class TbUtilsTest {
@Test
public void numberToString_Test() {
Assertions.assertEquals("11001101100110", TbUtils.intLongToString(13158L, 2));
Assertions.assertEquals("1111111111111111111111111111111111111111111111111111111110011010", TbUtils.intLongToString(-102L, 2));
Assertions.assertEquals("1111111111111111111111111111111111111111111111111100110010011010", TbUtils.intLongToString(-13158L, 2));
Assertions.assertEquals("00111010", TbUtils.intLongToString(58L, MIN_RADIX));
Assertions.assertEquals("0000000010011110", TbUtils.intLongToString(158L, MIN_RADIX));
Assertions.assertEquals("00000000000000100000001000000001", TbUtils.intLongToString(131585L, MIN_RADIX));
Assertions.assertEquals("0111111111111111111111111111111111111111111111111111111111111111", TbUtils.intLongToString(Long.MAX_VALUE, MIN_RADIX));
Assertions.assertEquals("1000000000000000000000000000000000000000000000000000000000000001", TbUtils.intLongToString(-Long.MAX_VALUE, MIN_RADIX));
Assertions.assertEquals("1111111111111111111111111111111111111111111111111111111110011010", TbUtils.intLongToString(-102L, MIN_RADIX));
Assertions.assertEquals("1111111111111111111111111111111111111111111111111100110010011010", TbUtils.intLongToString(-13158L, MIN_RADIX));
Assertions.assertEquals("777777777777777777777", TbUtils.intLongToString(Long.MAX_VALUE, 8));
Assertions.assertEquals("1000000000000000000000", TbUtils.intLongToString(Long.MIN_VALUE, 8));
Assertions.assertEquals("9223372036854775807", TbUtils.intLongToString(Long.MAX_VALUE));
@ -770,16 +774,22 @@ public class TbUtilsTest {
Assertions.assertEquals(toList(expected), actual);
try {
input = "0x01752B0367FA000500010488FFFFFFFFFFFFFFFF3";
actual = TbUtils.hexToBytes(ctx, input);
TbUtils.hexToBytes(ctx, input);
} catch (IllegalArgumentException e) {
Assertions.assertTrue(e.getMessage().contains("Hex string must be even-length."));
}
try {
input = "0x01752B0367KA000500010488FFFFFFFFFFFFFFFF33";
actual = TbUtils.hexToBytes(ctx, input);
TbUtils.hexToBytes(ctx, input);
} catch (NumberFormatException e) {
Assertions.assertTrue(e.getMessage().contains("Value: \"" + input + "\" is not numeric or hexDecimal format!"));
}
try {
input = "";
TbUtils.hexToBytes(ctx, input);
} catch (IllegalArgumentException e) {
Assertions.assertTrue(e.getMessage().contains("Hex string must be not empty"));
}
}
@Test
@ -900,6 +910,105 @@ public class TbUtilsTest {
Assertions.assertEquals(-1, TbUtils.isHexadecimal("K100110"));
}
@Test
public void padStart_Test() {
String binaryString = "010011";
String expected = "00010011";
Assertions.assertEquals(expected, TbUtils.padStart(binaryString, 8, '0'));
binaryString = "1001010011";
expected = "1001010011";
Assertions.assertEquals(expected, TbUtils.padStart(binaryString, 8, '0'));
binaryString = "1001010011";
expected = "******1001010011";
Assertions.assertEquals(expected, TbUtils.padStart(binaryString, 16, '*'));
String fullNumber = "203439900FFCD5581";
String last4Digits = fullNumber.substring(11);
expected = "***********CD5581";
Assertions.assertEquals(expected, TbUtils.padStart(last4Digits, fullNumber.length(), '*'));
}
@Test
public void padEnd_Test() {
String binaryString = "010011";
String expected = "01001100";
Assertions.assertEquals(expected, TbUtils.padEnd(binaryString, 8, '0'));
binaryString = "1001010011";
expected = "1001010011";
Assertions.assertEquals(expected, TbUtils.padEnd(binaryString, 8, '0'));
binaryString = "1001010011";
expected = "1001010011******";
Assertions.assertEquals(expected, TbUtils.padEnd(binaryString, 16, '*'));
String fullNumber = "203439900FFCD5581";
String last4Digits = fullNumber.substring(0, 11);
expected = "203439900FF******";
Assertions.assertEquals(expected, TbUtils.padEnd(last4Digits, fullNumber.length(), '*'));
}
@Test
public void parseByteToBinaryArray_Test() {
byte byteVal = 0x39;
int[] bitArray = {1, 0, 0, 1, 1, 1, 0, 0};
List expected = Arrays.stream(bitArray).boxed().toList();
int[] actualArray = TbUtils.parseByteToBinaryArray(byteVal);
List<Integer> actual = Arrays.stream(actualArray).boxed().toList();
Assertions.assertEquals(expected, actual);
bitArray = new int[]{1, 0, 0, 1, 1, 1};
expected = Arrays.stream(bitArray).boxed().toList();
actualArray = TbUtils.parseByteToBinaryArray(byteVal, bitArray.length);
actual = Arrays.stream(actualArray).boxed().toList();
Assertions.assertEquals(expected, actual);
}
@Test
public void parseBytesToBinaryArray_Test() {
long longValue = 57L;
byte[] bytesValue = new byte[]{0x39}; // 57
List<Byte> listValue = toList(bytesValue);
int[] bitArray = {1, 0, 0, 1, 1, 1, 0, 0};
List expected = Arrays.stream(bitArray).boxed().toList();
int[] actualArray = TbUtils.parseBytesToBinaryArray(listValue);
List<Integer> actual = Arrays.stream(actualArray).boxed().toList();
Assertions.assertEquals(expected, actual);
actualArray = TbUtils.parseLongToBinaryArray(longValue, listValue.size() * 8);
actual = Arrays.stream(actualArray).boxed().toList();
Assertions.assertEquals(expected, actual);
bitArray = new int[]{1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
expected = Arrays.stream(bitArray).boxed().toList();
actualArray = TbUtils.parseLongToBinaryArray(longValue);
actual = Arrays.stream(actualArray).boxed().toList();
Assertions.assertEquals(expected, actual);
longValue = 52914L;
bytesValue = new byte[]{(byte) 0xCE, (byte) 0xB2}; // 52914
listValue = toList(bytesValue);
bitArray = new int[]{0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1};
expected = Arrays.stream(bitArray).boxed().toList();
actualArray = TbUtils.parseBytesToBinaryArray(listValue);
actual = Arrays.stream(actualArray).boxed().toList();
Assertions.assertEquals(expected, actual);
actualArray = TbUtils.parseLongToBinaryArray(longValue, listValue.size() * 8);
actual = Arrays.stream(actualArray).boxed().toList();
Assertions.assertEquals(expected, actual);
bitArray = new int[]{0, 1, 0, 0};
expected = Arrays.stream(bitArray).boxed().toList();
actualArray = TbUtils.parseLongToBinaryArray(longValue, 4);
actual = Arrays.stream(actualArray).boxed().toList();
Assertions.assertEquals(expected, actual);
bitArray = new int[]{0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
expected = Arrays.stream(bitArray).boxed().toList();
actualArray = TbUtils.parseLongToBinaryArray(longValue);
actual = Arrays.stream(actualArray).boxed().toList();
Assertions.assertEquals(expected, actual);
}
private static List<Byte> toList(byte[] data) {
List<Byte> result = new ArrayList<>(data.length);
for (Byte b : data) {

Loading…
Cancel
Save