diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/repository/BaseRepository.java b/scim-core/src/main/java/org/apache/directory/scim/core/repository/BaseRepository.java new file mode 100644 index 000000000..256e54063 --- /dev/null +++ b/scim-core/src/main/java/org/apache/directory/scim/core/repository/BaseRepository.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.directory.scim.core.repository; + +import org.apache.directory.scim.spec.exception.ResourceException; +import org.apache.directory.scim.spec.exception.ResourceNotFoundException; +import org.apache.directory.scim.spec.patch.PatchOperation; +import org.apache.directory.scim.spec.resources.ScimResource; + +import java.util.List; + +/** + * Optional base class for {@link Repository} implementations that provides default + * implementations for common boilerplate methods. + * + *

Subclasses must implement {@link #create}, {@link #update}, {@link #get}, + * {@link #find}, and {@link #delete}. The following are provided automatically:

+ * + * + *

Usage example:

+ *
+ * @Named
+ * @ApplicationScoped
+ * public class MyUserRepository extends BaseRepository<ScimUser> {
+ *   @Inject
+ *   public MyUserRepository(PatchHandler patchHandler) {
+ *     super(ScimUser.class, patchHandler);
+ *   }
+ *   // implement create, update, get, find, delete
+ * }
+ * 
+ * + * @param the SCIM resource type this repository manages + */ +public abstract class BaseRepository implements Repository { + + private final Class resourceClass; + private final PatchHandler patchHandler; + + /** + * Creates a new base repository. + * + * @param resourceClass the SCIM resource class this repository manages + * @param patchHandler the handler used to apply SCIM PATCH operations + */ + protected BaseRepository(Class resourceClass, PatchHandler patchHandler) { + this.resourceClass = resourceClass; + this.patchHandler = patchHandler; + } + + /** + * No-arg constructor for CDI proxy creation. Subclasses using CDI must also + * provide a no-arg constructor that calls {@code super()}. + */ + protected BaseRepository() { + this.resourceClass = null; + this.patchHandler = null; + } + + @Override + public Class getResourceClass() { + return resourceClass; + } + + /** + * Default PATCH implementation: fetches the current resource, applies the patch + * operations, and persists the result via {@link #update}. + * + *

Subclasses may override this method if their backend supports more efficient + * partial-update semantics.

+ * + * {@inheritDoc} + */ + @Override + public T patch(String id, List patchOperations, + ScimRequestContext requestContext) throws ResourceException { + if (patchHandler == null) { + throw new IllegalStateException("No PatchHandler configured; patch() is not available on this instance"); + } + T current = get(id, requestContext); + if (current == null) { + throw new ResourceNotFoundException(id); + } + T patched = patchHandler.apply(current, patchOperations); + return update(id, patched, requestContext); + } +} diff --git a/scim-core/src/test/java/org/apache/directory/scim/core/repository/BaseRepositoryTest.java b/scim-core/src/test/java/org/apache/directory/scim/core/repository/BaseRepositoryTest.java new file mode 100644 index 000000000..5cb290e58 --- /dev/null +++ b/scim-core/src/test/java/org/apache/directory/scim/core/repository/BaseRepositoryTest.java @@ -0,0 +1,240 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.directory.scim.core.repository; + +import org.apache.directory.scim.spec.exception.ResourceException; +import org.apache.directory.scim.spec.exception.ResourceNotFoundException; +import org.apache.directory.scim.spec.filter.Filter; +import org.apache.directory.scim.spec.filter.FilterResponse; +import org.apache.directory.scim.spec.patch.PatchOperation; +import org.apache.directory.scim.spec.resources.ScimUser; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class BaseRepositoryTest { + + /** + * Concrete test subclass that delegates abstract methods to mockable lambdas. + */ + static class TestRepository extends BaseRepository { + + TestRepository(PatchHandler patchHandler) { + super(ScimUser.class, patchHandler); + } + + /** No-arg constructor to verify CDI proxy path. */ + TestRepository() { + super(); + } + + @Override + public ScimUser create(ScimUser resource, ScimRequestContext requestContext) { + return null; + } + + @Override + public ScimUser update(String id, ScimUser resource, ScimRequestContext requestContext) { + return resource; + } + + @Override + public ScimUser get(String id, ScimRequestContext requestContext) { + return null; + } + + @Override + public FilterResponse find(Filter filter, ScimRequestContext requestContext) { + return null; + } + + @Override + public void delete(String id) { + } + } + + @Test + void getResourceClass_returnsClassPassedToConstructor() { + PatchHandler patchHandler = Mockito.mock(PatchHandler.class); + TestRepository repository = new TestRepository(patchHandler); + + assertThat(repository.getResourceClass()).isEqualTo(ScimUser.class); + } + + @Test + void noArgConstructor_doesNotThrow() { + TestRepository repository = new TestRepository(); + + assertThat(repository.getResourceClass()).isNull(); + } + + @Test + void patch_callsGetThenApplyThenUpdate() throws ResourceException { + PatchHandler patchHandler = Mockito.mock(PatchHandler.class); + TestRepository repository = Mockito.spy(new TestRepository(patchHandler)); + + ScimUser existing = new ScimUser(); + existing.setId("user-1"); + ScimUser patched = new ScimUser(); + patched.setId("user-1-patched"); + ScimUser updated = new ScimUser(); + updated.setId("user-1-updated"); + + List ops = List.of(new PatchOperation()); + ScimRequestContext ctx = ScimRequestContext.empty(); + + when(repository.get("user-1", ctx)).thenReturn(existing); + when(patchHandler.apply(existing, ops)).thenReturn(patched); + when(repository.update("user-1", patched, ctx)).thenReturn(updated); + + ScimUser result = repository.patch("user-1", ops, ctx); + + assertThat(result).isSameAs(updated); + verify(repository).get("user-1", ctx); + verify(patchHandler).apply(existing, ops); + verify(repository).update("user-1", patched, ctx); + } + + @Test + void patch_throwsResourceNotFoundExceptionWhenGetReturnsNull() throws ResourceException { + PatchHandler patchHandler = Mockito.mock(PatchHandler.class); + TestRepository repository = Mockito.spy(new TestRepository(patchHandler)); + + ScimRequestContext ctx = ScimRequestContext.empty(); + when(repository.get("missing-id", ctx)).thenReturn(null); + + assertThatThrownBy(() -> repository.patch("missing-id", List.of(), ctx)) + .isInstanceOf(ResourceNotFoundException.class); + } + + @Test + void patch_passesCorrectIdOperationsAndContext() throws ResourceException { + PatchHandler patchHandler = Mockito.mock(PatchHandler.class); + TestRepository repository = Mockito.spy(new TestRepository(patchHandler)); + + ScimUser existing = new ScimUser(); + ScimUser patched = new ScimUser(); + ScimUser updated = new ScimUser(); + + PatchOperation op1 = new PatchOperation(); + PatchOperation op2 = new PatchOperation(); + List ops = List.of(op1, op2); + ScimRequestContext ctx = ScimRequestContext.empty(); + + when(repository.get("id-42", ctx)).thenReturn(existing); + when(patchHandler.apply(existing, ops)).thenReturn(patched); + when(repository.update("id-42", patched, ctx)).thenReturn(updated); + + repository.patch("id-42", ops, ctx); + + verify(repository).get(eq("id-42"), eq(ctx)); + verify(patchHandler).apply(eq(existing), eq(ops)); + verify(repository).update(eq("id-42"), eq(patched), eq(ctx)); + } + + @Test + void patch_returnsResultFromUpdate() throws ResourceException { + PatchHandler patchHandler = Mockito.mock(PatchHandler.class); + TestRepository repository = Mockito.spy(new TestRepository(patchHandler)); + + ScimUser existing = new ScimUser(); + ScimUser patched = new ScimUser(); + ScimUser updateResult = new ScimUser(); + updateResult.setId("final-result"); + + ScimRequestContext ctx = ScimRequestContext.empty(); + when(repository.get("id-1", ctx)).thenReturn(existing); + when(patchHandler.apply(any(), any())).thenReturn(patched); + when(repository.update(any(), any(), any())).thenReturn(updateResult); + + ScimUser result = repository.patch("id-1", List.of(), ctx); + + assertThat(result).isSameAs(updateResult); + assertThat(result.getId()).isEqualTo("final-result"); + } + + @Test + void patch_doesNotCallUpdateWhenGetReturnsNull() throws ResourceException { + PatchHandler patchHandler = Mockito.mock(PatchHandler.class); + TestRepository repository = Mockito.spy(new TestRepository(patchHandler)); + + ScimRequestContext ctx = ScimRequestContext.empty(); + when(repository.get("absent", ctx)).thenReturn(null); + + try { + repository.patch("absent", List.of(), ctx); + } catch (ResourceNotFoundException e) { + // expected + } + + verify(repository, Mockito.never()).update(any(), any(), any()); + verify(patchHandler, Mockito.never()).apply(any(), any()); + } + + @Test + void patch_doesNotCallApplyWhenGetReturnsNull() throws ResourceException { + PatchHandler patchHandler = Mockito.mock(PatchHandler.class); + TestRepository repository = Mockito.spy(new TestRepository(patchHandler)); + + ScimRequestContext ctx = ScimRequestContext.empty(); + when(repository.get("no-such", ctx)).thenReturn(null); + + try { + repository.patch("no-such", List.of(), ctx); + } catch (ResourceNotFoundException e) { + // expected + } + + verify(patchHandler, Mockito.never()).apply(any(), any()); + } + + @Test + void patch_nullPatchHandler_throwsIllegalStateException() { + TestRepository repository = Mockito.spy(new TestRepository(null)); + + assertThatThrownBy(() -> repository.patch("id", List.of(), ScimRequestContext.empty())) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("No PatchHandler configured"); + } + + @Test + void patch_patchHandlerThrowsException_propagates() throws ResourceException { + PatchHandler patchHandler = Mockito.mock(PatchHandler.class); + TestRepository repository = Mockito.spy(new TestRepository(patchHandler)); + + ScimUser user = new ScimUser(); + user.setId("id1"); + ScimRequestContext ctx = ScimRequestContext.empty(); + when(repository.get("id1", ctx)).thenReturn(user); + when(patchHandler.apply(any(), any())).thenThrow(new RuntimeException("patch failed")); + + assertThatThrownBy(() -> repository.patch("id1", List.of(), ctx)) + .isInstanceOf(RuntimeException.class) + .hasMessage("patch failed"); + } +} diff --git a/scim-server-examples/scim-server-jersey-4/src/main/java/org/apache/directory/scim/example/jersey4/service/InMemoryGroupService.java b/scim-server-examples/scim-server-jersey-4/src/main/java/org/apache/directory/scim/example/jersey4/service/InMemoryGroupService.java index ad1bdab81..0b92c8784 100644 --- a/scim-server-examples/scim-server-jersey-4/src/main/java/org/apache/directory/scim/example/jersey4/service/InMemoryGroupService.java +++ b/scim-server-examples/scim-server-jersey-4/src/main/java/org/apache/directory/scim/example/jersey4/service/InMemoryGroupService.java @@ -25,8 +25,8 @@ import jakarta.inject.Named; import jakarta.ws.rs.core.Response; import org.apache.commons.lang3.StringUtils; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.core.repository.ScimRequestContext; @@ -36,7 +36,6 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.ScimExtension; import org.apache.directory.scim.spec.resources.ScimGroup; @@ -48,18 +47,16 @@ @Named @ApplicationScoped -public class InMemoryGroupService implements Repository { +public class InMemoryGroupService extends BaseRepository { private final Map groups = new ConcurrentHashMap<>(); private SchemaRegistry schemaRegistry; - private PatchHandler patchHandler; - @Inject public InMemoryGroupService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimGroup.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } protected InMemoryGroupService() {} @@ -73,11 +70,6 @@ public void init() { groups.put(group.getId(), group); } - @Override - public Class getResourceClass() { - return ScimGroup.class; - } - @Override public ScimGroup create(ScimGroup resource, ScimRequestContext requestContext) throws UnableToCreateResourceException { String id = UUID.randomUUID().toString(); @@ -109,16 +101,6 @@ public ScimGroup update(String id, ScimGroup resource, ScimRequestContext reques return resource; } - @Override - public ScimGroup patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!groups.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimGroup resource = patchHandler.apply(get(id, requestContext), patchOperations); - groups.put(id, resource); - return resource; - } - @Override public ScimGroup get(String id, ScimRequestContext requestContext) { return groups.get(id); diff --git a/scim-server-examples/scim-server-jersey-4/src/main/java/org/apache/directory/scim/example/jersey4/service/InMemoryUserService.java b/scim-server-examples/scim-server-jersey-4/src/main/java/org/apache/directory/scim/example/jersey4/service/InMemoryUserService.java index 8c6649458..30d17cf7f 100644 --- a/scim-server-examples/scim-server-jersey-4/src/main/java/org/apache/directory/scim/example/jersey4/service/InMemoryUserService.java +++ b/scim-server-examples/scim-server-jersey-4/src/main/java/org/apache/directory/scim/example/jersey4/service/InMemoryUserService.java @@ -24,8 +24,8 @@ import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.ws.rs.core.Response; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.example.jersey4.extensions.LuckyNumberExtension; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; @@ -37,11 +37,9 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.Email; import org.apache.directory.scim.spec.resources.Name; import org.apache.directory.scim.spec.resources.ScimExtension; -import org.apache.directory.scim.spec.resources.ScimResource; import org.apache.directory.scim.spec.resources.ScimUser; import java.util.List; @@ -57,7 +55,7 @@ */ @Named @ApplicationScoped -public class InMemoryUserService implements Repository { +public class InMemoryUserService extends BaseRepository { static final String DEFAULT_USER_ID = UUID.randomUUID().toString(); static final String DEFAULT_USER_EXTERNAL_ID = "e" + DEFAULT_USER_ID; @@ -70,12 +68,10 @@ public class InMemoryUserService implements Repository { private SchemaRegistry schemaRegistry; - private PatchHandler patchHandler; - @Inject public InMemoryUserService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimUser.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } protected InMemoryUserService() {} @@ -112,11 +108,6 @@ public void init() { users.put(user.getId(), user); } - @Override - public Class getResourceClass() { - return ScimUser.class; - } - /** * @see Repository#create(ScimResource, ScimRequestContext) */ @@ -146,16 +137,6 @@ public ScimUser update(String id, ScimUser resource, ScimRequestContext requestC return resource; } - @Override - public ScimUser patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!users.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimUser resource = patchHandler.apply(get(id, requestContext), patchOperations); - users.put(id, resource); - return resource; - } - /** * @see Repository#get(java.lang.String, ScimRequestContext) */ diff --git a/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryGroupService.java b/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryGroupService.java index 1a34ea4ce..90cf74184 100644 --- a/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryGroupService.java +++ b/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryGroupService.java @@ -25,8 +25,8 @@ import jakarta.inject.Named; import jakarta.ws.rs.core.Response; import org.apache.commons.lang3.StringUtils; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.core.repository.ScimRequestContext; @@ -36,7 +36,6 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.ScimExtension; import org.apache.directory.scim.spec.resources.ScimGroup; @@ -48,18 +47,16 @@ @Named @ApplicationScoped -public class InMemoryGroupService implements Repository { +public class InMemoryGroupService extends BaseRepository { private final Map groups = new ConcurrentHashMap<>(); private SchemaRegistry schemaRegistry; - private PatchHandler patchHandler; - @Inject public InMemoryGroupService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimGroup.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } protected InMemoryGroupService() {} @@ -73,11 +70,6 @@ public void init() { groups.put(group.getId(), group); } - @Override - public Class getResourceClass() { - return ScimGroup.class; - } - @Override public ScimGroup create(ScimGroup resource, ScimRequestContext requestContext) throws UnableToCreateResourceException { String id = UUID.randomUUID().toString(); @@ -109,16 +101,6 @@ public ScimGroup update(String id, ScimGroup resource, ScimRequestContext reques return resource; } - @Override - public ScimGroup patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!groups.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimGroup resource = patchHandler.apply(get(id, requestContext), patchOperations); - groups.put(id, resource); - return resource; - } - @Override public ScimGroup get(String id, ScimRequestContext requestContext) { return groups.get(id); diff --git a/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryUserService.java b/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryUserService.java index dbb4b6991..0e8b9cd1b 100644 --- a/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryUserService.java +++ b/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryUserService.java @@ -24,8 +24,8 @@ import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.ws.rs.core.Response; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.example.jersey.extensions.LuckyNumberExtension; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; @@ -37,11 +37,9 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.Email; import org.apache.directory.scim.spec.resources.Name; import org.apache.directory.scim.spec.resources.ScimExtension; -import org.apache.directory.scim.spec.resources.ScimResource; import org.apache.directory.scim.spec.resources.ScimUser; import java.util.List; @@ -57,7 +55,7 @@ */ @Named @ApplicationScoped -public class InMemoryUserService implements Repository { +public class InMemoryUserService extends BaseRepository { static final String DEFAULT_USER_ID = UUID.randomUUID().toString(); static final String DEFAULT_USER_EXTERNAL_ID = "e" + DEFAULT_USER_ID; @@ -70,12 +68,10 @@ public class InMemoryUserService implements Repository { private SchemaRegistry schemaRegistry; - private PatchHandler patchHandler; - @Inject public InMemoryUserService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimUser.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } protected InMemoryUserService() {} @@ -112,11 +108,6 @@ public void init() { users.put(user.getId(), user); } - @Override - public Class getResourceClass() { - return ScimUser.class; - } - /** * @see Repository#create(ScimResource, ScimRequestContext) */ @@ -146,16 +137,6 @@ public ScimUser update(String id, ScimUser resource, ScimRequestContext requestC return resource; } - @Override - public ScimUser patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!users.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimUser resource = patchHandler.apply(get(id, requestContext), patchOperations); - users.put(id, resource); - return resource; - } - /** * @see Repository#get(java.lang.String, ScimRequestContext) */ diff --git a/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryGroupService.java b/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryGroupService.java index 532bf043d..8d0a66d2e 100644 --- a/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryGroupService.java +++ b/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryGroupService.java @@ -25,8 +25,8 @@ import jakarta.inject.Named; import jakarta.ws.rs.core.Response; import org.apache.commons.lang3.StringUtils; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.core.repository.ScimRequestContext; @@ -36,7 +36,6 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.ScimExtension; import org.apache.directory.scim.spec.resources.ScimGroup; @@ -48,18 +47,16 @@ @Named @ApplicationScoped -public class InMemoryGroupService implements Repository { +public class InMemoryGroupService extends BaseRepository { private final Map groups = new ConcurrentHashMap<>(); private SchemaRegistry schemaRegistry; - private PatchHandler patchHandler; - @Inject public InMemoryGroupService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimGroup.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } protected InMemoryGroupService() {} @@ -73,11 +70,6 @@ public void init() { groups.put(group.getId(), group); } - @Override - public Class getResourceClass() { - return ScimGroup.class; - } - @Override public ScimGroup create(ScimGroup resource, ScimRequestContext requestContext) throws UnableToCreateResourceException { String id = UUID.randomUUID().toString(); @@ -109,16 +101,6 @@ public ScimGroup update(String id, ScimGroup resource, ScimRequestContext reques return resource; } - @Override - public ScimGroup patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!groups.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimGroup resource = patchHandler.apply(get(id, requestContext), patchOperations); - groups.put(id, resource); - return resource; - } - @Override public ScimGroup get(String id, ScimRequestContext requestContext) { return groups.get(id); diff --git a/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryUserService.java b/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryUserService.java index 1f63bdb75..34a15cdcf 100644 --- a/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryUserService.java +++ b/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryUserService.java @@ -24,8 +24,8 @@ import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.ws.rs.core.Response; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.example.memory.extensions.LuckyNumberExtension; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; @@ -37,11 +37,9 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.Email; import org.apache.directory.scim.spec.resources.Name; import org.apache.directory.scim.spec.resources.ScimExtension; -import org.apache.directory.scim.spec.resources.ScimResource; import org.apache.directory.scim.spec.resources.ScimUser; import java.util.List; @@ -57,7 +55,7 @@ */ @Named @ApplicationScoped -public class InMemoryUserService implements Repository { +public class InMemoryUserService extends BaseRepository { static final String DEFAULT_USER_ID = UUID.randomUUID().toString(); static final String DEFAULT_USER_EXTERNAL_ID = "e" + DEFAULT_USER_ID; @@ -70,12 +68,10 @@ public class InMemoryUserService implements Repository { private SchemaRegistry schemaRegistry; - private PatchHandler patchHandler; - @Inject public InMemoryUserService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimUser.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } protected InMemoryUserService() {} @@ -112,11 +108,6 @@ public void init() { users.put(user.getId(), user); } - @Override - public Class getResourceClass() { - return ScimUser.class; - } - /** * @see Repository#create(ScimResource, ScimRequestContext) */ @@ -146,16 +137,6 @@ public ScimUser update(String id, ScimUser resource, ScimRequestContext requestC return resource; } - @Override - public ScimUser patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!users.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimUser resource = patchHandler.apply(get(id, requestContext), patchOperations); - users.put(id, resource); - return resource; - } - /** * @see Repository#get(java.lang.String, ScimRequestContext) */ diff --git a/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryGroupService.java b/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryGroupService.java index 13c26e978..39e03ce5a 100644 --- a/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryGroupService.java +++ b/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryGroupService.java @@ -25,8 +25,8 @@ import jakarta.inject.Named; import jakarta.ws.rs.core.Response; import org.apache.commons.lang3.StringUtils; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.core.repository.ScimRequestContext; @@ -36,7 +36,6 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.ScimExtension; import org.apache.directory.scim.spec.resources.ScimGroup; @@ -48,18 +47,16 @@ @Named @ApplicationScoped -public class InMemoryGroupService implements Repository { +public class InMemoryGroupService extends BaseRepository { private final Map groups = new ConcurrentHashMap<>(); private SchemaRegistry schemaRegistry; - private PatchHandler patchHandler; - @Inject public InMemoryGroupService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimGroup.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } protected InMemoryGroupService() {} @@ -73,11 +70,6 @@ public void init() { groups.put(group.getId(), group); } - @Override - public Class getResourceClass() { - return ScimGroup.class; - } - @Override public ScimGroup create(ScimGroup resource, ScimRequestContext requestContext) throws UnableToCreateResourceException { String id = UUID.randomUUID().toString(); @@ -109,16 +101,6 @@ public ScimGroup update(String id, ScimGroup resource, ScimRequestContext reques return resource; } - @Override - public ScimGroup patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!groups.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimGroup resource = patchHandler.apply(get(id, requestContext), patchOperations); - groups.put(id, resource); - return resource; - } - @Override public ScimGroup get(String id, ScimRequestContext requestContext) { return groups.get(id); diff --git a/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryUserService.java b/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryUserService.java index 182205acd..a15b3a04a 100644 --- a/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryUserService.java +++ b/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryUserService.java @@ -24,8 +24,8 @@ import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.ws.rs.core.Response; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.example.quarkus.extensions.LuckyNumberExtension; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; @@ -37,11 +37,9 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.Email; import org.apache.directory.scim.spec.resources.Name; import org.apache.directory.scim.spec.resources.ScimExtension; -import org.apache.directory.scim.spec.resources.ScimResource; import org.apache.directory.scim.spec.resources.ScimUser; import java.util.List; @@ -57,7 +55,7 @@ */ @Named @ApplicationScoped -public class InMemoryUserService implements Repository { +public class InMemoryUserService extends BaseRepository { static final String DEFAULT_USER_ID = UUID.randomUUID().toString(); static final String DEFAULT_USER_EXTERNAL_ID = "e" + DEFAULT_USER_ID; @@ -70,12 +68,10 @@ public class InMemoryUserService implements Repository { private SchemaRegistry schemaRegistry; - private PatchHandler patchHandler; - @Inject public InMemoryUserService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimUser.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } protected InMemoryUserService() {} @@ -112,11 +108,6 @@ public void init() { users.put(user.getId(), user); } - @Override - public Class getResourceClass() { - return ScimUser.class; - } - /** * @see Repository#create(ScimResource, ScimRequestContext) */ @@ -146,16 +137,6 @@ public ScimUser update(String id, ScimUser resource, ScimRequestContext requestC return resource; } - @Override - public ScimUser patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!users.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimUser resource = patchHandler.apply(get(id, requestContext), patchOperations); - users.put(id, resource); - return resource; - } - /** * @see Repository#get(java.lang.String, ScimRequestContext) */ diff --git a/scim-server-examples/scim-server-spring-boot-4/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryGroupService.java b/scim-server-examples/scim-server-spring-boot-4/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryGroupService.java index 7afe668f8..ab02a6513 100644 --- a/scim-server-examples/scim-server-spring-boot-4/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryGroupService.java +++ b/scim-server-examples/scim-server-spring-boot-4/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryGroupService.java @@ -21,8 +21,8 @@ import jakarta.annotation.PostConstruct; import jakarta.ws.rs.core.Response; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.core.repository.ScimRequestContext; @@ -32,7 +32,6 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.ScimExtension; import org.apache.directory.scim.spec.resources.ScimGroup; import org.springframework.stereotype.Service; @@ -45,17 +44,15 @@ import java.util.concurrent.ConcurrentHashMap; @Service -public class InMemoryGroupService implements Repository { +public class InMemoryGroupService extends BaseRepository { private final Map groups = new ConcurrentHashMap<>(); private final SchemaRegistry schemaRegistry; - private final PatchHandler patchHandler; - public InMemoryGroupService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimGroup.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } @PostConstruct @@ -67,11 +64,6 @@ public void init() { groups.put(group.getId(), group); } - @Override - public Class getResourceClass() { - return ScimGroup.class; - } - @Override public ScimGroup create(ScimGroup resource, ScimRequestContext requestContext) throws UnableToCreateResourceException { String id = UUID.randomUUID().toString(); @@ -103,16 +95,6 @@ public ScimGroup update(String id, ScimGroup resource, ScimRequestContext reques return resource; } - @Override - public ScimGroup patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!groups.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimGroup resource = patchHandler.apply(get(id, requestContext), patchOperations); - groups.put(id, resource); - return resource; - } - @Override public ScimGroup get(String id, ScimRequestContext requestContext) { return groups.get(id); diff --git a/scim-server-examples/scim-server-spring-boot-4/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java b/scim-server-examples/scim-server-spring-boot-4/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java index 382474107..053b1ff67 100644 --- a/scim-server-examples/scim-server-spring-boot-4/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java +++ b/scim-server-examples/scim-server-spring-boot-4/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java @@ -21,8 +21,8 @@ import jakarta.annotation.PostConstruct; import jakarta.ws.rs.core.Response; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.example.spring.extensions.LuckyNumberExtension; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; @@ -34,11 +34,9 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.Email; import org.apache.directory.scim.spec.resources.Name; import org.apache.directory.scim.spec.resources.ScimExtension; -import org.apache.directory.scim.spec.resources.ScimResource; import org.apache.directory.scim.spec.resources.ScimUser; import org.springframework.stereotype.Service; @@ -54,7 +52,7 @@ * @author Chris Harm <crh5255@psu.edu> */ @Service -public class InMemoryUserService implements Repository { +public class InMemoryUserService extends BaseRepository { static final String DEFAULT_USER_ID = UUID.randomUUID().toString(); static final String DEFAULT_USER_EXTERNAL_ID = "e" + DEFAULT_USER_ID; @@ -67,11 +65,9 @@ public class InMemoryUserService implements Repository { private final SchemaRegistry schemaRegistry; - private final PatchHandler patchHandler; - public InMemoryUserService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimUser.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } @PostConstruct @@ -106,11 +102,6 @@ public void init() { users.put(user.getId(), user); } - @Override - public Class getResourceClass() { - return ScimUser.class; - } - /** * @see Repository#create(ScimResource, ScimRequestContext) */ @@ -140,16 +131,6 @@ public ScimUser update(String id, ScimUser resource, ScimRequestContext requestC return resource; } - @Override - public ScimUser patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!users.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimUser resource = patchHandler.apply(get(id, requestContext), patchOperations); - users.put(id, resource); - return resource; - } - /** * @see Repository#get(java.lang.String, ScimRequestContext) */ diff --git a/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryGroupService.java b/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryGroupService.java index 7afe668f8..ab02a6513 100644 --- a/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryGroupService.java +++ b/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryGroupService.java @@ -21,8 +21,8 @@ import jakarta.annotation.PostConstruct; import jakarta.ws.rs.core.Response; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.core.repository.ScimRequestContext; @@ -32,7 +32,6 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.ScimExtension; import org.apache.directory.scim.spec.resources.ScimGroup; import org.springframework.stereotype.Service; @@ -45,17 +44,15 @@ import java.util.concurrent.ConcurrentHashMap; @Service -public class InMemoryGroupService implements Repository { +public class InMemoryGroupService extends BaseRepository { private final Map groups = new ConcurrentHashMap<>(); private final SchemaRegistry schemaRegistry; - private final PatchHandler patchHandler; - public InMemoryGroupService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimGroup.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } @PostConstruct @@ -67,11 +64,6 @@ public void init() { groups.put(group.getId(), group); } - @Override - public Class getResourceClass() { - return ScimGroup.class; - } - @Override public ScimGroup create(ScimGroup resource, ScimRequestContext requestContext) throws UnableToCreateResourceException { String id = UUID.randomUUID().toString(); @@ -103,16 +95,6 @@ public ScimGroup update(String id, ScimGroup resource, ScimRequestContext reques return resource; } - @Override - public ScimGroup patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!groups.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimGroup resource = patchHandler.apply(get(id, requestContext), patchOperations); - groups.put(id, resource); - return resource; - } - @Override public ScimGroup get(String id, ScimRequestContext requestContext) { return groups.get(id); diff --git a/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java b/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java index 382474107..053b1ff67 100644 --- a/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java +++ b/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java @@ -21,8 +21,8 @@ import jakarta.annotation.PostConstruct; import jakarta.ws.rs.core.Response; +import org.apache.directory.scim.core.repository.BaseRepository; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.example.spring.extensions.LuckyNumberExtension; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; @@ -34,11 +34,9 @@ import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; import org.apache.directory.scim.spec.filter.PageRequest; -import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.Email; import org.apache.directory.scim.spec.resources.Name; import org.apache.directory.scim.spec.resources.ScimExtension; -import org.apache.directory.scim.spec.resources.ScimResource; import org.apache.directory.scim.spec.resources.ScimUser; import org.springframework.stereotype.Service; @@ -54,7 +52,7 @@ * @author Chris Harm <crh5255@psu.edu> */ @Service -public class InMemoryUserService implements Repository { +public class InMemoryUserService extends BaseRepository { static final String DEFAULT_USER_ID = UUID.randomUUID().toString(); static final String DEFAULT_USER_EXTERNAL_ID = "e" + DEFAULT_USER_ID; @@ -67,11 +65,9 @@ public class InMemoryUserService implements Repository { private final SchemaRegistry schemaRegistry; - private final PatchHandler patchHandler; - public InMemoryUserService(SchemaRegistry schemaRegistry, PatchHandler patchHandler) { + super(ScimUser.class, patchHandler); this.schemaRegistry = schemaRegistry; - this.patchHandler = patchHandler; } @PostConstruct @@ -106,11 +102,6 @@ public void init() { users.put(user.getId(), user); } - @Override - public Class getResourceClass() { - return ScimUser.class; - } - /** * @see Repository#create(ScimResource, ScimRequestContext) */ @@ -140,16 +131,6 @@ public ScimUser update(String id, ScimUser resource, ScimRequestContext requestC return resource; } - @Override - public ScimUser patch(String id, List patchOperations, ScimRequestContext requestContext) throws ResourceException { - if (!users.containsKey(id)) { - throw new ResourceNotFoundException(id); - } - ScimUser resource = patchHandler.apply(get(id, requestContext), patchOperations); - users.put(id, resource); - return resource; - } - /** * @see Repository#get(java.lang.String, ScimRequestContext) */