You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by bd...@apache.org on 2023/01/06 23:38:29 UTC
[directory-scimple] 01/01: Remove the use of Jackson when processing patches
This is an automated email from the ASF dual-hosted git repository.
bdemers pushed a commit to branch patch_phase1_no_jackson
in repository https://gitbox.apache.org/repos/asf/directory-scimple.git
commit ba09f2018cbe8c2a45a6c091bec7bbecb52597d6
Author: Brian Demers <bd...@apache.org>
AuthorDate: Fri Jan 6 18:38:22 2023 -0500
Remove the use of Jackson when processing patches
- FitlerExpressions.inMemory() now returns Predicate<Object> instead of KeyedResource
- Added test for complex patch filter
---
.../scim/core/repository/PatchHandlerImpl.java | 48 ++++------------------
.../scim/core/repository/PatchHandlerTest.java | 32 ++++++++++++++-
.../scim/spec/filter/FilterExpressions.java | 3 +-
3 files changed, 41 insertions(+), 42 deletions(-)
diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/repository/PatchHandlerImpl.java b/scim-core/src/main/java/org/apache/directory/scim/core/repository/PatchHandlerImpl.java
index c623c6d5..aa10e27e 100644
--- a/scim-core/src/main/java/org/apache/directory/scim/core/repository/PatchHandlerImpl.java
+++ b/scim-core/src/main/java/org/apache/directory/scim/core/repository/PatchHandlerImpl.java
@@ -19,34 +19,23 @@
package org.apache.directory.scim.core.repository;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.SerializationUtils;
-import org.apache.directory.scim.core.json.ObjectMapperFactory;
import org.apache.directory.scim.core.schema.SchemaRegistry;
import org.apache.directory.scim.spec.filter.*;
import org.apache.directory.scim.spec.filter.attribute.AttributeReference;
import org.apache.directory.scim.spec.patch.PatchOperation;
import org.apache.directory.scim.spec.patch.PatchOperationPath;
-import org.apache.directory.scim.spec.resources.KeyedResource;
import org.apache.directory.scim.spec.resources.ScimResource;
import org.apache.directory.scim.spec.schema.Schema;
import org.apache.directory.scim.spec.schema.Schema.Attribute;
import java.util.*;
import java.util.function.Predicate;
-import java.util.stream.Collectors;
@SuppressWarnings("unchecked")
@Slf4j
public class PatchHandlerImpl implements PatchHandler {
-
- private static final TypeReference<Map<String, Object>> MAP_TYPE = new TypeReference<>() {
- };
-
- private final ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper();
-
private final SchemaRegistry schemaRegistry;
public PatchHandlerImpl(SchemaRegistry schemaRegistry) {
@@ -88,7 +77,6 @@ public class PatchHandlerImpl implements PatchHandler {
}
private <T extends ScimResource> T apply(final T source, final PatchOperation patchOperation) {
- Map<String, Object> sourceAsMap = objectAsMap(source);
final ValuePathExpression valuePathExpression = valuePathExpression(patchOperation);
final AttributeReference attributeReference = attributeReference(valuePathExpression);
@@ -104,28 +92,19 @@ public class PatchHandlerImpl implements PatchHandler {
if (valuePathExpression.getAttributeExpression() != null && attributeObject instanceof Collection<?>) {
// apply expression filter
Collection<Object> items = (Collection<Object>) attributeObject;
- Collection<Object> updatedCollection = items.stream().map(item -> {
- KeyedResource keyedResource = (KeyedResource) item;
- Map<String, Object> keyedResourceAsMap = objectAsMap(item);
- Predicate<KeyedResource> pred = FilterExpressions.inMemory(valuePathExpression.getAttributeExpression(), baseSchema);
- if (pred.test(keyedResource)) {
+ items.forEach(item -> {
+ Predicate<Object> pred = FilterExpressions.inMemory(valuePathExpression.getAttributeExpression(), baseSchema);
+ if (pred.test(item)) {
String subAttributeName = valuePathExpression.getAttributePath().getSubAttributeName();
- if (keyedResourceAsMap.get(subAttributeName) == null && patchOperation.getOperation().equals(PatchOperation.Type.REPLACE)) {
- throw new IllegalArgumentException("Cannot apply patch replace on missing property: " + valuePathExpression.toFilter());
- }
- keyedResourceAsMap.put(subAttributeName, patchOperation.getValue());
- return keyedResourceAsMap;
- } else {
- // filter does not apply
- return item;
+ Schema.AttributeAccessor subAttributeAccessor = attribute.getAttribute(subAttributeName).getAccessor();
+ subAttributeAccessor.set(item, patchOperation.getValue());
}
- }).collect(Collectors.toList());
- sourceAsMap.put(attribute.getName(), updatedCollection);
+ });
} else {
- // no filter expression
- sourceAsMap.put(attribute.getName(), patchOperation.getValue());
+ // no filter expression, just set the value
+ attribute.getAccessor().set(source, patchOperation.getValue());
}
- return (T) mapAsScimResource(sourceAsMap, source.getClass());
+ return source;
}
private PatchOperationPath tryGetOperationPath(String key) {
@@ -137,14 +116,6 @@ public class PatchHandlerImpl implements PatchHandler {
}
}
- private <T extends ScimResource> T mapAsScimResource(final Map<String, Object> scimResourceAsMap, final Class<T> clazz) {
- return objectMapper.convertValue(scimResourceAsMap, clazz);
- }
-
- private Map<String, Object> objectAsMap(final Object object) {
- return objectMapper.convertValue(object, MAP_TYPE);
- }
-
public static ValuePathExpression valuePathExpression(final PatchOperation operation) {
return Optional.ofNullable(operation.getPath())
.map(PatchOperationPath::getValuePathExpression)
@@ -155,5 +126,4 @@ public class PatchHandlerImpl implements PatchHandler {
return Optional.ofNullable(expression.getAttributePath())
.orElseThrow(() -> new IllegalArgumentException("Patch operation must have an expression with a valid attribute path"));
}
-
}
diff --git a/scim-core/src/test/java/org/apache/directory/scim/core/repository/PatchHandlerTest.java b/scim-core/src/test/java/org/apache/directory/scim/core/repository/PatchHandlerTest.java
index 508eb59f..4d8d8d66 100644
--- a/scim-core/src/test/java/org/apache/directory/scim/core/repository/PatchHandlerTest.java
+++ b/scim-core/src/test/java/org/apache/directory/scim/core/repository/PatchHandlerTest.java
@@ -23,6 +23,7 @@ import org.apache.directory.scim.core.schema.SchemaRegistry;
import org.apache.directory.scim.spec.filter.FilterParseException;
import org.apache.directory.scim.spec.patch.PatchOperation;
import org.apache.directory.scim.spec.patch.PatchOperationPath;
+import org.apache.directory.scim.spec.resources.Email;
import org.apache.directory.scim.spec.resources.ScimUser;
import org.apache.directory.scim.spec.schema.Schemas;
import org.junit.jupiter.api.Test;
@@ -58,11 +59,40 @@ public class PatchHandlerTest {
assertThat(updatedUser.getUserName()).isEqualTo("testUser_updated");
}
+ @Test
+ public void applyWithFilterExpression() throws FilterParseException {
+ PatchOperation op = new PatchOperation();
+ op.setOperation(PatchOperation.Type.REPLACE);
+ op.setPath(new PatchOperationPath("emails[type EQ \"home\"].value"));
+ op.setValue("new-home@example.com");
+ ScimUser updatedUser = performPatch(op);
+ List<Email> emails = updatedUser.getEmails();
+ assertThat(emails).isEqualTo(List.of(
+ new Email()
+ .setPrimary(true)
+ .setType("work")
+ .setValue("work@example.com"),
+ new Email()
+ .setType("home")
+ .setValue("new-home@example.com") // updated email
+ ));
+ }
+
private ScimUser performPatch(PatchOperation op) {
when(mockSchemaRegistry.getSchema(ScimUser.SCHEMA_URI)).thenReturn(Schemas.schemaFor(ScimUser.class));
- PatchHandlerImpl patchHandler = new PatchHandlerImpl(mockSchemaRegistry);
+ PatchHandler patchHandler = new PatchHandlerImpl(mockSchemaRegistry);
ScimUser user = new ScimUser();
user.setUserName("testUser");
+ user.setEmails(List.of(
+ new Email()
+ .setPrimary(true)
+ .setType("work")
+ .setValue("work@example.com"),
+ new Email()
+ .setType("home")
+ .setValue("home@example.com")
+ ));
+
return patchHandler.apply(user, List.of(op));
}
}
diff --git a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/filter/FilterExpressions.java b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/filter/FilterExpressions.java
index e9d2300f..531788dc 100644
--- a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/filter/FilterExpressions.java
+++ b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/filter/FilterExpressions.java
@@ -1,6 +1,5 @@
package org.apache.directory.scim.spec.filter;
-import org.apache.directory.scim.spec.resources.KeyedResource;
import org.apache.directory.scim.spec.resources.ScimResource;
import org.apache.directory.scim.spec.schema.Schema;
@@ -29,7 +28,7 @@ public final class FilterExpressions {
return InMemoryScimFilterMatcher.toPredicate(expression, schema);
}
- public static Predicate<KeyedResource> inMemory(FilterExpression expression, Schema schema) {
+ public static Predicate<Object> inMemory(FilterExpression expression, Schema schema) {
return InMemoryScimFilterMatcher.toPredicate(expression, schema);
}
}