Skip to content

Commit

Permalink
fix: permit query asset json properties
Browse files Browse the repository at this point in the history
  • Loading branch information
ndr-brt committed Oct 23, 2023
1 parent cba9558 commit efcea29
Show file tree
Hide file tree
Showing 23 changed files with 493 additions and 658 deletions.
2 changes: 2 additions & 0 deletions core/common/util/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ plugins {
}

dependencies {
api(project(":spi:common:core-spi"))

testImplementation(libs.junit.pioneer)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

package org.eclipse.edc.util.reflection;

import org.eclipse.edc.spi.types.PathItem;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
Expand Down Expand Up @@ -47,29 +49,34 @@ public static <T> T getFieldValue(String propertyName, Object object) {
Objects.requireNonNull(propertyName, "propertyName");
Objects.requireNonNull(object, "object");

if (propertyName.contains(".")) {
var dotIx = propertyName.indexOf(".");
var field = propertyName.substring(0, dotIx);
var rest = propertyName.substring(dotIx + 1);
object = getFieldValue(field, object);
if (object == null) {
var path = PathItem.parse(propertyName);
return getFieldValue(path, object);
}

private static <T> T getFieldValue(List<PathItem> path, Object object) {
var first = path.get(0);

if (path.size() > 1) {
var nested = getFieldValue(List.of(first), object);
if (nested == null) {
return null;
}
return getFieldValue(rest, object);
} else if (propertyName.matches(ARRAY_INDEXER_REGEX)) { //array indexer
var openingBracketIx = propertyName.indexOf(OPENING_BRACKET);
var closingBracketIx = propertyName.indexOf(CLOSING_BRACKET);
var propName = propertyName.substring(0, openingBracketIx);
var arrayIndex = Integer.parseInt(propertyName.substring(openingBracketIx + 1, closingBracketIx));
var rest = path.stream().skip(1).toList();
return getFieldValue(rest, nested);
} else if (first.toString().matches(ARRAY_INDEXER_REGEX)) { //array indexer
var openingBracketIx = first.toString().indexOf(OPENING_BRACKET);
var closingBracketIx = first.toString().indexOf(CLOSING_BRACKET);
var propName = first.toString().substring(0, openingBracketIx);
var arrayIndex = Integer.parseInt(first.toString().substring(openingBracketIx + 1, closingBracketIx));

Check notice

Code scanning / CodeQL

Missing catch of NumberFormatException Note

Potential uncaught 'java.lang.NumberFormatException'.
var iterableObject = (List) getFieldValue(propName, object);
return (T) iterableObject.get(arrayIndex);
} else {
if (object instanceof Map<?, ?> map) {
return (T) map.get(propertyName);
return (T) map.get(first.toString());
} else if (object instanceof List<?> list) {
return (T) list.stream().filter(Objects::nonNull).map(it -> getRecursiveValue(propertyName, it)).toList();
return (T) list.stream().filter(Objects::nonNull).map(it -> getRecursiveValue(first.toString(), it)).toList();
} else {
return getRecursiveValue(propertyName, object);
return getRecursiveValue(first.toString(), object);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.eclipse.edc.util.reflection;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
Expand All @@ -27,154 +28,177 @@

class ReflectionUtilTest {

@Test
void getFieldValue() {
var value = ReflectionUtil.getFieldValue("description", new TestObject("test-desc", 1));
assertThat(value).isInstanceOf(String.class).isEqualTo("test-desc");
@Nested
class GetFieldValue {

@Test
void getFieldValue() {
var value = ReflectionUtil.getFieldValue("description", new TestObject("test-desc", 1));
assertThat(value).isInstanceOf(String.class).isEqualTo("test-desc");

var value2 = ReflectionUtil.getFieldValue("priority", new TestObject("test-desc", 1));
assertThat(value2).isInstanceOf(Integer.class).isEqualTo(1);
}
var value2 = ReflectionUtil.getFieldValue("priority", new TestObject("test-desc", 1));
assertThat(value2).isInstanceOf(Integer.class).isEqualTo(1);
}

@Test
void getFieldValue_isNull() {
var value = ReflectionUtil.getFieldValue("description", new TestObject(null, 1));
assertThat(value).isNull();
}
@Test
void getFieldValue_isNull() {
var value = ReflectionUtil.getFieldValue("description", new TestObject(null, 1));
assertThat(value).isNull();
}

@Test
void getFieldValue_notExist() {
assertThatThrownBy(() -> ReflectionUtil.getFieldValue("notExist", new TestObject("test-desc", 1)))
.isInstanceOf(ReflectionException.class);
}
@Test
void getFieldValue_notExist() {
assertThatThrownBy(() -> ReflectionUtil.getFieldValue("notExist", new TestObject("test-desc", 1)))
.isInstanceOf(ReflectionException.class);
}

@Test
void getFieldValue_invalidArgs() {
@Test
void getFieldValue_invalidArgs() {

assertThatThrownBy(() -> ReflectionUtil.getFieldValue("", new TestObject("test-desc", 1)))
.isInstanceOf(ReflectionException.class);
assertThatThrownBy(() -> ReflectionUtil.getFieldValue("", new TestObject("test-desc", 1)))
.isInstanceOf(ReflectionException.class);

assertThatThrownBy(() -> ReflectionUtil.getFieldValue(null, new TestObject("test-desc", 1)))
.isInstanceOf(NullPointerException.class).hasMessage("propertyName");
assertThatThrownBy(() -> ReflectionUtil.getFieldValue((String) null, new TestObject("test-desc", 1)))
.isInstanceOf(NullPointerException.class).hasMessage("propertyName");

assertThatThrownBy(() -> ReflectionUtil.getFieldValue("description", null))
.isInstanceOf(NullPointerException.class).hasMessage("object");
}
assertThatThrownBy(() -> ReflectionUtil.getFieldValue("description", null))
.isInstanceOf(NullPointerException.class).hasMessage("object");
}

@Test
void getFieldValue_fromMap() {
var value = ReflectionUtil.getFieldValue("key", Map.of("key", "value"));
@Test
void getFieldValue_fromMap() {
var value = ReflectionUtil.getFieldValue("key", Map.of("key", "value"));

assertThat(value).isEqualTo("value");
}
assertThat(value).isEqualTo("value");
}

@Test
void getAllFieldsRecursive() {
var to = new TestObjectSubclass("test-desc", 1, "foobar");
@Test
void getFieldValue_whenParentExist() {
var to = new TestObjectSubSubclass("test-desc", 1, "foobar");
to.setAnotherObject(new AnotherObject("another-desc"));

assertThat(ReflectionUtil.getAllFieldsRecursive(to.getClass())).hasSize(5).extracting(Field::getName)
.containsExactlyInAnyOrder("description", "priority", "testProperty", "listField", "embedded");
}
String fieldValue = ReflectionUtil.getFieldValue("anotherObject.anotherDescription", to);
assertThat(fieldValue).isEqualTo("another-desc");
}

@Test
void getFieldRecursive_whenDeclaredInSuperclass() {
var to = new TestObjectSubclass("test-desc", 1, "foobar");
assertThat(ReflectionUtil.getFieldRecursive(to.getClass(), "description")).isNotNull();
}
@Test
void getFieldValue_whenParentNotExist() {
var to = new TestObjectSubSubclass("test-desc", 1, "foobar");
to.setAnotherObject(null);

@Test
void getFieldRecursive_whenDeclaredInClass() {
var to = new TestObjectSubclass("test-desc", 1, "foobar");
String fieldValue = ReflectionUtil.getFieldValue("anotherObject.anotherDescription", to);
assertThat(fieldValue).isNull();
}

var testProperty = ReflectionUtil.getFieldRecursive(to.getClass(), "testProperty");
@Test
void getFieldValue_withArrayIndex() {
var to1 = new TestObject("to1", 420);
var o = new TestObjectWithList("test-desc", 0, List.of(to1, new TestObject("to2", 69)));
assertThat((TestObject) ReflectionUtil.getFieldValue("nestedObjects[0]", o)).isEqualTo(to1);
}

assertThat(testProperty).isNotNull();
}
@Test
void getFieldValue_arrayWithoutIndex() {
var nestedObjects = List.of(
new TestObject("to1", 420),
new TestObject("to2", 69)
);
var object = new TestObjectWithList("test-desc", 0, nestedObjects);

@Test
@DisplayName("Should pick the property from the object highest in the object hierarchy")
void getFieldRecursive_whenDeclaredInBoth() {
var to = new TestObjectSubSubclass("test-desc", 2, "foobar");
assertThat(ReflectionUtil.getFieldRecursive(to.getClass(), "description")).isNotNull().extracting(Field::getDeclaringClass)
.isEqualTo(TestObject.class);
}
var result = ReflectionUtil.getFieldValue("nestedObjects.description", object);

@Test
void getFieldRecursive_whenNotDeclared() {
var to = new TestObjectSubclass("test-desc", 1, "foobar");
assertThat(ReflectionUtil.getFieldRecursive(to.getClass(), "notExist")).isNull();
}
assertThat(result).isEqualTo(List.of("to1", "to2"));
}

@Test
void getFieldValue_whenParentExist() {
var to = new TestObjectSubSubclass("test-desc", 1, "foobar");
to.setAnotherObject(new AnotherObject("another-desc"));
@Test
void getFieldValue_withArrayIndex_andDotAccess() {
var to1 = new TestObject("to1", 420);
var o = new TestObjectWithList("test-desc", 0, List.of(to1, new TestObject("to2", 69)));

String fieldValue = ReflectionUtil.getFieldValue("anotherObject.anotherDescription", to);
assertThat(fieldValue).isEqualTo("another-desc");
}
var fieldValue = ReflectionUtil.getFieldValue("nestedObjects[0].priority", o);

@Test
void getFieldValue_whenParentNotExist() {
var to = new TestObjectSubSubclass("test-desc", 1, "foobar");
to.setAnotherObject(null);
assertThat(fieldValue).isEqualTo(420);
}

String fieldValue = ReflectionUtil.getFieldValue("anotherObject.anotherDescription", to);
assertThat(fieldValue).isNull();
}
@Test
void getFieldValue_withArrayIndex_outOfBounds() {
var o = new TestObjectWithList("test-desc", 0, List.of(new TestObject("to1", 420), new TestObject("to2", 69)));
assertThatThrownBy(() -> ReflectionUtil.getFieldValue("nestedObjects[3]", o)).isInstanceOf(IndexOutOfBoundsException.class);
}

@Test
void getFieldValue_withArrayIndex() {
var to1 = new TestObject("to1", 420);
var o = new TestObjectWithList("test-desc", 0, List.of(to1, new TestObject("to2", 69)));
assertThat((TestObject) ReflectionUtil.getFieldValue("nestedObjects[0]", o)).isEqualTo(to1);
}
@Test
void shouldGetNestedValue_whenKeyContainsDot() {
var object = Map.of("http://namespace.domain/nested", Map.of("http://namespace.domain/key", "value"));

@Test
void getFieldValue_arrayWithoutIndex() {
var nestedObjects = List.of(
new TestObject("to1", 420),
new TestObject("to2", 69)
);
var object = new TestObjectWithList("test-desc", 0, nestedObjects);
var value = ReflectionUtil.getFieldValue("'http://namespace.domain/nested'.'http://namespace.domain/key'", object);

var result = ReflectionUtil.getFieldValue("nestedObjects.description", object);
assertThat(value).isInstanceOf(String.class).isEqualTo("value");
}

assertThat(result).isEqualTo(List.of("to1", "to2"));
}

@Test
void getFieldValue_withArrayIndex_andDotAccess() {
var to1 = new TestObject("to1", 420);
var o = new TestObjectWithList("test-desc", 0, List.of(to1, new TestObject("to2", 69)));
@Nested
class GetFieldRecursive {

var fieldValue = ReflectionUtil.getFieldValue("nestedObjects[0].priority", o);
@Test
void getAllFieldsRecursive() {
var to = new TestObjectSubclass("test-desc", 1, "foobar");

assertThat(fieldValue).isEqualTo(420);
}
assertThat(ReflectionUtil.getAllFieldsRecursive(to.getClass())).hasSize(5).extracting(Field::getName)
.containsExactlyInAnyOrder("description", "priority", "testProperty", "listField", "embedded");
}

@Test
void getFieldValue_withArrayIndex_outOfBounds() {
var o = new TestObjectWithList("test-desc", 0, List.of(new TestObject("to1", 420), new TestObject("to2", 69)));
assertThatThrownBy(() -> ReflectionUtil.getFieldValue("nestedObjects[3]", o)).isInstanceOf(IndexOutOfBoundsException.class);
}
@Test
void getFieldRecursive_whenDeclaredInSuperclass() {
var to = new TestObjectSubclass("test-desc", 1, "foobar");
assertThat(ReflectionUtil.getFieldRecursive(to.getClass(), "description")).isNotNull();
}

@Test
void getSingleSuperTypeGenericArgument() {
var fields = ReflectionUtil.getSingleSuperTypeGenericArgument(TestGenericSubclass.class, TestGenericObject.class);
assertThat(fields).isEqualTo(String.class);
}
@Test
void getFieldRecursive_whenDeclaredInClass() {
var to = new TestObjectSubclass("test-desc", 1, "foobar");

var testProperty = ReflectionUtil.getFieldRecursive(to.getClass(), "testProperty");

assertThat(testProperty).isNotNull();
}

@Test
@DisplayName("Should pick the property from the object highest in the object hierarchy")
void getFieldRecursive_whenDeclaredInBoth() {
var to = new TestObjectSubSubclass("test-desc", 2, "foobar");
assertThat(ReflectionUtil.getFieldRecursive(to.getClass(), "description")).isNotNull().extracting(Field::getDeclaringClass)
.isEqualTo(TestObject.class);
}

@Test
void getFieldRecursive_whenNotDeclared() {
var to = new TestObjectSubclass("test-desc", 1, "foobar");
assertThat(ReflectionUtil.getFieldRecursive(to.getClass(), "notExist")).isNull();
}

@Test
void getSingleSuperTypeGenericArgument_whenNoGenericSuperclass() {
var fields = ReflectionUtil.getSingleSuperTypeGenericArgument(TestObjectWithList.class, TestObject.class);
assertThat(fields).isNull();
}

@Test
void getSingleSuperTypeGenericArgument_whenGenericClass() {
var genericList = new TestGenericArrayList<String>();
var fields = ReflectionUtil.getSingleSuperTypeGenericArgument(genericList.getClass(), ArrayList.class);
assertThat(fields).isNull();
@Nested
class GetSingleSuperTypeGenericArgument {
@Test
void getSingleSuperTypeGenericArgument() {
var fields = ReflectionUtil.getSingleSuperTypeGenericArgument(TestGenericSubclass.class, TestGenericObject.class);
assertThat(fields).isEqualTo(String.class);
}

@Test
void getSingleSuperTypeGenericArgument_whenNoGenericSuperclass() {
var fields = ReflectionUtil.getSingleSuperTypeGenericArgument(TestObjectWithList.class, TestObject.class);
assertThat(fields).isNull();
}

@Test
void getSingleSuperTypeGenericArgument_whenGenericClass() {
var genericList = new TestGenericArrayList<String>();
var fields = ReflectionUtil.getSingleSuperTypeGenericArgument(genericList.getClass(), ArrayList.class);
assertThat(fields).isNull();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.eclipse.edc.spi.dataaddress.DataAddressValidator;
import org.eclipse.edc.spi.query.Criterion;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.spi.types.domain.DataAddress;
import org.eclipse.edc.spi.types.domain.asset.Asset;
import org.eclipse.edc.transaction.spi.TransactionContext;

Expand Down Expand Up @@ -124,12 +123,4 @@ public ServiceResult<Asset> update(Asset asset) {
});
}

@Override
public ServiceResult<DataAddress> update(String assetId, DataAddress dataAddress) {
return transactionContext.execute(() -> {
var result = index.updateDataAddress(assetId, dataAddress);
result.onSuccess(da -> observable.invokeForEach(l -> l.updated(findById(assetId))));
return ServiceResult.from(result);
});
}
}
Loading

0 comments on commit efcea29

Please sign in to comment.