Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -221,30 +221,29 @@ private static Object writeToValueAtRange(

if (dimension == dimensionCount) {
if (current.getClass().isArray()) {
Class<?> currentType = ArrayUtil.getType(current);
Class<?> updateType = ArrayUtil.getType(update);

if (currentType != updateType) {
if (ArrayUtil.getBoxedType(current) != ArrayUtil.getBoxedType(update)) {
throw new UaException(
StatusCodes.Bad_TypeMismatch,
String.format("currentType=%s, updateType=%s", current, update));
String.format(
"current=%s, update=%s",
ArrayUtil.getBoxedType(current), ArrayUtil.getBoxedType(update)));
}

int length = Array.getLength(current);
Object copy = Array.newInstance(currentType, length);
Object copy = Array.newInstance(ArrayUtil.getType(current), length);

if (low >= length || high >= length) {
throw new UaException(StatusCodes.Bad_IndexRangeNoData);
}

for (int i = 0; i < length; i++) {
Object element;
if (i < low || i > high) {
Object element = Array.get(current, i);
Array.set(copy, i, element);
element = Array.get(current, i);
} else {
Object element = Array.get(update, i - low);
Array.set(copy, i, element);
element = Array.get(update, i - low);
}
Array.set(copy, i, element);
}

return copy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,28 @@ public void testWriteByteString() throws UaException {
assertEquals(new ByteString(new byte[] {0, 2, 4, 3}), updated);
}

@Test
void writePrimitiveUpdateToBoxedCurrent() throws UaException {
Variant current = new Variant(new Integer[] {0, 1, 2, 3});
Variant update = new Variant(new int[] {2, 4});
NumericRange range = NumericRange.parse("1:2");

Object updated = NumericRange.writeToValueAtRange(current, update, range);
assertInstanceOf(Integer[].class, updated);
assertArrayEquals(new Integer[] {0, 2, 4, 3}, (Integer[]) updated);
}

@Test
void writeBoxedUpdateToPrimitiveCurrent() throws UaException {
Variant current = new Variant(new int[] {0, 1, 2, 3});
Variant update = new Variant(new Integer[] {2, 4});
NumericRange range = NumericRange.parse("1:2");

Object updated = NumericRange.writeToValueAtRange(current, update, range);
assertInstanceOf(int[].class, updated);
assertArrayEquals(new int[] {0, 2, 4, 3}, (int[]) updated);
}

private static Object[][] getInvalidRanges() {
return new Object[][] {
{"0:0"}, {"1:1"}, {"-4:0"}, {"0:-4"}, {"3:1"}, {"abc,def"}, {"1:2,3:1"},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 the Eclipse Milo Authors
* Copyright (c) 2025 the Eclipse Milo Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -124,6 +124,12 @@ public static int getValueRank(Object array) {
return rank == 0 ? -1 : rank;
}

/**
* Get the base component type for the provided array.
*
* @param array the array whose base component type is to be determined.
* @return the {@code Class} object representing the base component type of the array.
*/
public static Class<?> getType(Object array) {
Class<?> type = array.getClass();

Expand All @@ -134,6 +140,27 @@ public static Class<?> getType(Object array) {
return type;
}

/**
* Get the (boxed) base component type for the provided array.
*
* @param array the array whose (boxed) base component type is to be determined.
* @return the {@code Class} object representing the (boxed) base component type of the array.
*/
public static Class<?> getBoxedType(Object array) {
Class<?> type = getType(array);

if (type == byte.class) return Byte.class;
if (type == short.class) return Short.class;
if (type == int.class) return Integer.class;
if (type == long.class) return Long.class;
if (type == float.class) return Float.class;
if (type == double.class) return Double.class;
if (type == char.class) return Character.class;
if (type == boolean.class) return Boolean.class;

return type;
}

/**
* If the provided Object is a primitive array, return a boxed array of the same type, otherwise
* return the original Object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,27 @@ public void testGetType(Object array, Class<?> type) throws Exception {
assertEquals(type, ArrayUtil.getType(array));
}

public static Object[][] getBoxedTypedArrays() {
return new Object[][] {
{new byte[1], Byte.class},
{new short[1], Short.class},
{new int[1], Integer.class},
{new long[1], Long.class},
{new float[1], Float.class},
{new double[1], Double.class},
{new char[1], Character.class},
{new boolean[1], Boolean.class},
{new Integer[1], Integer.class},
{new String[1], String.class},
};
}

@ParameterizedTest
@MethodSource("getBoxedTypedArrays")
public void testGetBoxedType(Object array, Class<?> type) throws Exception {
assertEquals(type, ArrayUtil.getBoxedType(array));
}

@Test
void getValueRank() {
assertEquals(-1, ArrayUtil.getValueRank(0));
Expand Down