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 2022/09/15 20:17:19 UTC
[directory-scimple] 01/01: Move schema reg logic out of RepoReg and into SchemaReg
This is an automated email from the ASF dual-hosted git repository.
bdemers pushed a commit to branch schema-reg
in repository https://gitbox.apache.org/repos/asf/directory-scimple.git
commit 3ecf17fb88a14f78fa7558f6503cb3b882c3905c
Author: Brian Demers <bd...@apache.org>
AuthorDate: Fri Sep 9 14:17:28 2022 -0400
Move schema reg logic out of RepoReg and into SchemaReg
Add a few tests
---
.../scim/core/repository/RepositoryRegistry.java | 26 ++----
.../directory/scim/core/schema/SchemaRegistry.java | 55 ++++++-----
.../core/repository/RepositoryRegistryTest.java | 101 +++++++++++++++++++++
.../scim/core/schema/SchemaRegistryTest.java | 66 ++++++++++++++
.../adapter/AttributeReferenceAdapterTest.java | 74 +++++++++++++++
.../scim/protocol/adapter/StatusAdapterTest.java | 53 +++++++++++
.../scim/spec/extension/ScimExtensionRegistry.java | 25 ++---
.../apache/directory/scim/spec/schema/Schema.java | 63 +++++++------
8 files changed, 376 insertions(+), 87 deletions(-)
diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/repository/RepositoryRegistry.java b/scim-core/src/main/java/org/apache/directory/scim/core/repository/RepositoryRegistry.java
index 19bf1490..f2db29f5 100644
--- a/scim-core/src/main/java/org/apache/directory/scim/core/repository/RepositoryRegistry.java
+++ b/scim-core/src/main/java/org/apache/directory/scim/core/repository/RepositoryRegistry.java
@@ -19,7 +19,6 @@
package org.apache.directory.scim.core.repository;
-import com.fasterxml.jackson.core.JsonProcessingException;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
@@ -74,38 +73,27 @@ public class RepositoryRegistry implements Initializable {
.forEach(repository -> {
try {
registerRepository(repository.getResourceClass(), repository);
- } catch (InvalidRepositoryException | JsonProcessingException | ResourceException e) {
+ } catch (InvalidRepositoryException | ResourceException e) {
throw new ScimResourceInvalidException("Failed to register repository " + repository.getClass() + " for ScimResource type " + repository.getResourceClass(), e);
}
});
}
- public synchronized <T extends ScimResource> void registerRepository(Class<T> clazz, Repository<T> repository) throws InvalidRepositoryException, JsonProcessingException, ResourceException {
+ public synchronized <T extends ScimResource> void registerRepository(Class<T> clazz, Repository<T> repository) throws InvalidRepositoryException, ResourceException {
ResourceType resourceType = generateResourceType(clazz, repository);
- log.info("Calling addSchema on the base class: {}", clazz);
- schemaRegistry.addSchema(Schemas.schemaFor(clazz));
- // NOTE generateResourceType() ensures ScimResourceType exists
- ScimResourceType scimResourceType = clazz.getAnnotation(ScimResourceType.class);
- String schemaUrn = scimResourceType.schema();
- String endpoint = scimResourceType.endpoint();
- schemaRegistry.addScimResourceSchemaUrn(schemaUrn, clazz);
- schemaRegistry.addScimResourceEndPoint(endpoint, clazz);
-
List<Class<? extends ScimExtension>> extensionList = repository.getExtensionList();
+ log.debug("Calling addSchema on the base class: {}", clazz);
+ schemaRegistry.addSchema(clazz, resourceType, extensionList);
+
if (extensionList != null) {
for (Class<? extends ScimExtension> scimExtension : extensionList) {
- log.info("Registering a extension of type: " + scimExtension);
+ log.debug("Registering a extension of type: " + scimExtension);
scimExtensionRegistry.registerExtension(clazz, scimExtension);
-
- log.info("Calling addSchema on an extension: " + scimExtension);
- schemaRegistry.addSchema(Schemas.schemaForExtension(scimExtension));
}
}
-
- schemaRegistry.addResourceType(resourceType);
repositoryMap.put(clazz, repository);
}
@@ -119,7 +107,7 @@ public class RepositoryRegistry implements Initializable {
ScimResourceType scimResourceType = base.getAnnotation(ScimResourceType.class);
if (scimResourceType == null) {
- throw new InvalidRepositoryException("Missing annotation: ScimResourceType must be at the top of scim resource classes");
+ throw new InvalidRepositoryException("Missing annotation: @ScimResourceType must be at the top of scim resource classes");
}
ResourceType resourceType = new ResourceType();
diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/schema/SchemaRegistry.java b/scim-core/src/main/java/org/apache/directory/scim/core/schema/SchemaRegistry.java
index bb573c05..37e5a0c5 100644
--- a/scim-core/src/main/java/org/apache/directory/scim/core/schema/SchemaRegistry.java
+++ b/scim-core/src/main/java/org/apache/directory/scim/core/schema/SchemaRegistry.java
@@ -19,20 +19,17 @@
package org.apache.directory.scim.core.schema;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.*;
import jakarta.enterprise.context.ApplicationScoped;
+import org.apache.directory.scim.spec.annotation.ScimResourceType;
+import org.apache.directory.scim.spec.exception.ScimResourceInvalidException;
+import org.apache.directory.scim.spec.resources.ScimExtension;
import org.apache.directory.scim.spec.resources.ScimResource;
import org.apache.directory.scim.spec.schema.ResourceType;
import org.apache.directory.scim.spec.schema.Schema;
import lombok.extern.slf4j.Slf4j;
+import org.apache.directory.scim.spec.schema.Schemas;
@Slf4j
@ApplicationScoped
@@ -46,8 +43,6 @@ public class SchemaRegistry {
private Map<String, ResourceType> resourceTypeMap = new HashMap<>();
- private ObjectMapper objectMapper;
-
public Schema getSchema(String urn) {
return schemaMap.get(urn);
}
@@ -70,26 +65,39 @@ public class SchemaRegistry {
return schemaMap.get(schemaUrn);
}
- public void addSchema(Schema schema) throws JsonProcessingException {
- log.info("Adding schema " + schema.getId() + " into the registry");
+ private void addSchema(Schema schema) {
+ log.debug("Adding schema " + schema.getId() + " into the registry");
schemaMap.put(schema.getId(), schema);
}
- public void addSchemaDoc(String schemaDoc) {
- // Unmarshall the JSON document to a Schema and its associated object graph.
- try {
- Schema schema = objectMapper.readValue(schemaDoc, Schema.class);
- schemaMap.put(schema.getId(), schema);
- } catch (Throwable t) {
- log.error("Unexpected Throwable was caught while unmarshalling JSON, schema will not be added: " + t.getLocalizedMessage());
+ public <T extends ScimResource> void addSchema(Class<T> clazz, ResourceType resourceType, List<Class<? extends ScimExtension>> extensionList) {
+
+ ScimResourceType scimResourceType = clazz.getAnnotation(ScimResourceType.class);
+ if (scimResourceType == null) {
+ throw new ScimResourceInvalidException("Missing annotation: ScimResource must be annotated with @ScimResourceType.");
+ }
+
+ String schemaUrn = scimResourceType.schema();
+ String endpoint = scimResourceType.endpoint();
+
+ addSchema(Schemas.schemaFor(clazz));
+ addScimResourceSchemaUrn(schemaUrn, clazz);
+ addScimResourceEndPoint(endpoint, clazz);
+ addResourceType(resourceType);
+
+ if (extensionList != null) {
+ for (Class<? extends ScimExtension> scimExtension : extensionList) {
+ log.debug("Calling addSchema on an extension: " + scimExtension);
+ addSchema(Schemas.schemaForExtension(scimExtension));
+ }
}
}
- public <T extends ScimResource> void addScimResourceSchemaUrn(String schemaUrn, Class<T> scimResourceClass) {
+ private <T extends ScimResource> void addScimResourceSchemaUrn(String schemaUrn, Class<T> scimResourceClass) {
schemaUrnToScimResourceClass.put(schemaUrn, scimResourceClass);
}
- public <T extends ScimResource> void addScimResourceEndPoint(String endpoint, Class<T> scimResourceClass) {
+ private <T extends ScimResource> void addScimResourceEndPoint(String endpoint, Class<T> scimResourceClass) {
endpointToScimResourceClass.put(endpoint, scimResourceClass);
}
@@ -114,9 +122,8 @@ public class SchemaRegistry {
public Collection<ResourceType> getAllResourceTypes() {
return Collections.unmodifiableCollection(resourceTypeMap.values());
}
-
- public void addResourceType(ResourceType resourceType) {
+
+ private void addResourceType(ResourceType resourceType) {
resourceTypeMap.put(resourceType.getName(), resourceType);
}
-
}
diff --git a/scim-core/src/test/java/org/apache/directory/scim/core/repository/RepositoryRegistryTest.java b/scim-core/src/test/java/org/apache/directory/scim/core/repository/RepositoryRegistryTest.java
new file mode 100644
index 00000000..f5e4f892
--- /dev/null
+++ b/scim-core/src/test/java/org/apache/directory/scim/core/repository/RepositoryRegistryTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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 jakarta.enterprise.inject.Instance;
+import org.apache.directory.scim.core.schema.SchemaRegistry;
+import org.apache.directory.scim.spec.annotation.ScimExtensionType;
+import org.apache.directory.scim.spec.annotation.ScimResourceType;
+import org.apache.directory.scim.spec.exception.ResourceException;
+import org.apache.directory.scim.spec.exception.ScimResourceInvalidException;
+import org.apache.directory.scim.spec.extension.ScimExtensionRegistry;
+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.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.*;
+
+public class RepositoryRegistryTest {
+
+ @Test
+ public void initializeWithException() throws InvalidRepositoryException, ResourceException {
+ SchemaRegistry schemaRegistry = new SchemaRegistry();
+ Instance<Repository<? extends ScimResource>> scimRepositoryInstances = mock(Instance.class);
+ Repository<ScimUser> repository = mock(Repository.class);
+ RepositoryRegistry repositoryRegistry = spy(new RepositoryRegistry(schemaRegistry, ScimExtensionRegistry.getInstance(), scimRepositoryInstances));
+
+ when(scimRepositoryInstances.stream()).thenReturn(Stream.of(repository));
+ doThrow(new InvalidRepositoryException("test exception")).when(repositoryRegistry).registerRepository(any(), any());
+
+ assertThrows(ScimResourceInvalidException.class, repositoryRegistry::initialize);
+ }
+
+ @Test
+ public void registerRepository() throws InvalidRepositoryException, ResourceException {
+ SchemaRegistry schemaRegistry = spy(new SchemaRegistry());
+ Instance<Repository<? extends ScimResource>> scimRepositoryInstances = mock(Instance.class);
+ Repository<StubResource> repository = mock(Repository.class);
+ ScimExtensionRegistry extensionRegistry = ScimExtensionRegistry.getInstance();
+ RepositoryRegistry repositoryRegistry = spy(new RepositoryRegistry(schemaRegistry, extensionRegistry, scimRepositoryInstances));
+
+ when(scimRepositoryInstances.stream()).thenReturn(Stream.of(repository));
+ when(repository.getExtensionList()).thenReturn(List.of(StubExtension.class));
+
+ // TODO: need to refactor out the ScimExtensionRegistry to make it easier for test
+ assertThat(extensionRegistry.getExtensionClass(StubResource.class, StubExtension.URN)).isNull();
+ repositoryRegistry.registerRepository(StubResource.class, repository);
+ assertThat(extensionRegistry.getExtensionClass(StubResource.class, StubExtension.URN)).isNotNull();
+
+ assertThat(repositoryRegistry.getRepository(StubResource.class)).isEqualTo(repository);
+ }
+
+ @ScimResourceType(id = StubResource.NAME, endpoint = "/Stub", schema = StubResource.URN)
+ static class StubResource extends ScimResource {
+
+ final static String URN = "urn:test:stub";
+ final static String NAME = "Stub";
+
+ public StubResource() {
+ super(URN);
+ }
+
+ @Override
+ public String getResourceType() {
+ return NAME;
+ }
+ }
+
+ @ScimExtensionType(name = StubExtension.NAME, id = StubExtension.URN)
+ static class StubExtension implements ScimExtension {
+ final static String URN = "urn:test:stub:extension";
+ final static String NAME = "StubExtension";
+
+ @Override
+ public String getUrn() {
+ return URN;
+ }
+ }
+}
diff --git a/scim-core/src/test/java/org/apache/directory/scim/core/schema/SchemaRegistryTest.java b/scim-core/src/test/java/org/apache/directory/scim/core/schema/SchemaRegistryTest.java
new file mode 100644
index 00000000..731ae1c2
--- /dev/null
+++ b/scim-core/src/test/java/org/apache/directory/scim/core/schema/SchemaRegistryTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.schema;
+
+import org.apache.directory.scim.core.repository.utility.ExampleObjectExtension;
+import org.apache.directory.scim.spec.resources.ScimGroup;
+import org.apache.directory.scim.spec.resources.ScimUser;
+import org.apache.directory.scim.spec.schema.ResourceType;
+import org.apache.directory.scim.spec.schema.Schema;
+import org.apache.directory.scim.spec.schema.Schemas;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SchemaRegistryTest {
+
+ @Test
+ public void registerSchema() {
+
+ SchemaRegistry schemaRegistry = new SchemaRegistry();
+ Schema userSchema = Schemas.schemaFor(ScimUser.class);
+ Schema groupsSchema = Schemas.schemaFor(ScimGroup.class);
+ Schema extSchema = Schemas.schemaForExtension(ExampleObjectExtension.class);
+
+ ResourceType userType = new ResourceType();
+ userType.setId("user");
+ userType.setSchemaUrn(ScimUser.SCHEMA_URI);
+ userType.setName(ScimUser.RESOURCE_NAME);
+ ResourceType groupType = new ResourceType();
+ groupType.setId("group");
+ groupType.setSchemaUrn(ScimGroup.SCHEMA_URI);
+ groupType.setName(ScimGroup.RESOURCE_NAME);
+
+ schemaRegistry.addSchema(ScimUser.class, userType, List.of(ExampleObjectExtension.class));
+ schemaRegistry.addSchema(ScimGroup.class, groupType, List.of());
+
+ assertThat(schemaRegistry.getSchema(ScimUser.SCHEMA_URI)).isEqualTo(userSchema);
+ assertThat(schemaRegistry.getAllSchemas()).containsOnly(userSchema, groupsSchema, extSchema);
+ assertThat(schemaRegistry.getAllSchemaUrns()).containsOnly(ScimUser.SCHEMA_URI, ScimGroup.SCHEMA_URI, ExampleObjectExtension.URN);
+ assertThat(schemaRegistry.getAllResourceTypes()).containsOnly(userType, groupType);
+ assertThat(schemaRegistry.getResourceType(ScimUser.RESOURCE_NAME)).isEqualTo(userType);
+ assertThat(schemaRegistry.findScimResourceClassFromEndpoint("/Users")).isEqualTo(ScimUser.class);
+ assertThat(schemaRegistry.findScimResourceClassFromEndpoint("/Groups")).isEqualTo(ScimGroup.class);
+ assertThat(schemaRegistry.findScimResourceClass(ScimUser.SCHEMA_URI)).isEqualTo(ScimUser.class);
+ assertThat(schemaRegistry.getBaseSchemaOfResourceType(ScimUser.RESOURCE_NAME)).isEqualTo(Schemas.schemaFor(ScimUser.class));
+ }
+}
diff --git a/scim-spec/scim-spec-protocol/src/test/java/org/apache/directory/scim/protocol/adapter/AttributeReferenceAdapterTest.java b/scim-spec/scim-spec-protocol/src/test/java/org/apache/directory/scim/protocol/adapter/AttributeReferenceAdapterTest.java
new file mode 100644
index 00000000..2bea5ba6
--- /dev/null
+++ b/scim-spec/scim-spec-protocol/src/test/java/org/apache/directory/scim/protocol/adapter/AttributeReferenceAdapterTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.protocol.adapter;
+
+import org.apache.directory.scim.spec.filter.attribute.AttributeReference;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class AttributeReferenceAdapterTest {
+
+ private static Map<String, AttributeReference> TEST_DATA = Map.of(
+ "urn:test:testAttributeName.testSubAttributeName", new AttributeReference("urn:test", "testAttributeName", "testSubAttributeName"),
+ "urn:test:testAttributeName", new AttributeReference("urn:test", "testAttributeName"),
+ "testAttributeName", new AttributeReference("testAttributeName")
+ );
+
+ @ParameterizedTest
+ @MethodSource("marshalTestArgs")
+ public void marshal(AttributeReference input, String expected) throws Exception {
+ assertThat(new AttributeReferenceAdapter().marshal(input)).isEqualTo(expected);
+ }
+
+ @Test
+ public void marshalNull() throws Exception {
+ String result = new AttributeReferenceAdapter().marshal(null);
+ assertThat(result).isNull();
+ }
+
+ @ParameterizedTest
+ @MethodSource("unmarshalTestArgs")
+ public void unmarshal(String input, AttributeReference expected) throws Exception {
+ assertThat(new AttributeReferenceAdapter().unmarshal(input)).isEqualTo(expected);
+ }
+
+ @Test
+ public void unmarshalNull() throws Exception {
+ AttributeReference result = new AttributeReferenceAdapter().unmarshal(null);
+ assertThat(result).isNull();
+ }
+
+ private static Stream<Arguments> unmarshalTestArgs() {
+ return TEST_DATA.entrySet().stream()
+ .map(e -> Arguments.of(e.getKey(), e.getValue()));
+ }
+
+ private static Stream<Arguments> marshalTestArgs() {
+ return TEST_DATA.entrySet().stream()
+ .map(e -> Arguments.of(e.getValue(), e.getKey()));
+ }
+}
diff --git a/scim-spec/scim-spec-protocol/src/test/java/org/apache/directory/scim/protocol/adapter/StatusAdapterTest.java b/scim-spec/scim-spec-protocol/src/test/java/org/apache/directory/scim/protocol/adapter/StatusAdapterTest.java
new file mode 100644
index 00000000..0b4e2b13
--- /dev/null
+++ b/scim-spec/scim-spec-protocol/src/test/java/org/apache/directory/scim/protocol/adapter/StatusAdapterTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.protocol.adapter;
+
+import jakarta.ws.rs.core.Response.Status;
+import org.apache.directory.scim.protocol.data.StatusAdapter;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class StatusAdapterTest {
+
+ @Test
+ public void marshal() throws Exception {
+ String result = new StatusAdapter().marshal(Status.CONFLICT);
+ assertThat(result).isEqualTo("409");
+ }
+
+ @Test
+ public void marshalNull() throws Exception {
+ String result = new StatusAdapter().marshal(null);
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void unmarshal() throws Exception {
+ Status result = new StatusAdapter().unmarshal("400");
+ assertThat(result).isEqualTo(Status.BAD_REQUEST);
+ }
+
+ @Test
+ public void unmarshalNull() throws Exception {
+ Status result = new StatusAdapter().unmarshal(null);
+ assertThat(result).isNull();
+ }
+}
diff --git a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/extension/ScimExtensionRegistry.java b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/extension/ScimExtensionRegistry.java
index 94a622fa..2a272b4b 100644
--- a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/extension/ScimExtensionRegistry.java
+++ b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/extension/ScimExtensionRegistry.java
@@ -33,11 +33,9 @@ public final class ScimExtensionRegistry {
private static final ScimExtensionRegistry INSTANCE = new ScimExtensionRegistry();
- private Map<Class<? extends ScimResource>, Map<String, Class<? extends ScimExtension>>> registry;
+ private Map<Class<? extends ScimResource>, Map<String, Class<? extends ScimExtension>>> registry = new HashMap<>();
- private ScimExtensionRegistry() {
- registry = new HashMap<Class<? extends ScimResource>, Map<String, Class<? extends ScimExtension>>>();
- }
+ private ScimExtensionRegistry() {}
public Class<? extends ScimExtension> getExtensionClass(Class<? extends ScimResource> resourceClass, String urn) {
Class<? extends ScimExtension> extensionClass = null;
@@ -57,22 +55,17 @@ public final class ScimExtensionRegistry {
public void registerExtension(Class<? extends ScimResource> resourceClass, Class<? extends ScimExtension> extensionClass) {
ScimExtensionType[] se = extensionClass.getAnnotationsByType(ScimExtensionType.class);
- if (se.length == 0 || se.length > 1) {
- throw new InvalidExtensionException("Registered extensions must have an ScimExtensionType annotation");
+ if (se.length != 1) {
+ throw new InvalidExtensionException("Registered extensions must a single @ScimExtensionType annotation");
}
String urn = se[0].id();
- log.debug("Registering extension for URN: " + urn);
- log.debug(" (associated resource class: " + resourceClass.getSimpleName() + ")");
- log.debug(" (associated extension class: " + extensionClass.getSimpleName() + ")");
-
- Map<String, Class<? extends ScimExtension>> resourceMap = registry.get(resourceClass);
- if(resourceMap == null) {
- resourceMap = new HashMap<>();
- registry.put(resourceClass, resourceMap);
- }
-
+ log.debug("Registering extension for URN: '{}' associated resource class: '{}' and extension class: '{}'",
+ urn, resourceClass.getSimpleName(), extensionClass.getSimpleName() );
+
+ Map<String, Class<? extends ScimExtension>> resourceMap = registry.computeIfAbsent(resourceClass, k -> new HashMap<>());
+
if(!resourceMap.containsKey(urn)) {
resourceMap.put(urn, extensionClass);
}
diff --git a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/schema/Schema.java b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/schema/Schema.java
index e13852b5..499e80f7 100644
--- a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/schema/Schema.java
+++ b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/schema/Schema.java
@@ -23,10 +23,7 @@ import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import jakarta.xml.bind.annotation.*;
-import lombok.AccessLevel;
-import lombok.Data;
-import lombok.Getter;
-import lombok.Setter;
+import lombok.*;
import org.apache.directory.scim.spec.exception.ScimResourceInvalidException;
import org.apache.directory.scim.spec.validator.Urn;
import org.slf4j.Logger;
@@ -252,32 +249,42 @@ public class Schema implements AttributeContainer {
Class<?> getType();
static AttributeAccessor forField(Field field) {
- return new AttributeAccessor() {
- @Override
- public <T> T get(Object resource) {
- try {
- field.setAccessible(true);
- return (T) field.get(resource);
- } catch (IllegalAccessException e) {
- throw new ScimResourceInvalidException("Schema definition is invalid", e);
- }
- }
+ return new FieldAttributeAccessor(field);
+ }
+ }
- @Override
- public void set(Object resource, Object value) {
- try {
- field.setAccessible(true);
- field.set(resource, value);
- } catch (IllegalAccessException e) {
- throw new ScimResourceInvalidException("Schema definition is invalid", e);
- }
- }
+ @EqualsAndHashCode
+ private static class FieldAttributeAccessor implements AttributeAccessor {
- @Override
- public Class<?> getType() {
- return field.getType();
- }
- };
+ private final Field field;
+
+ public FieldAttributeAccessor(Field field) {
+ this.field = field;
+ }
+
+ @Override
+ public <T> T get(Object resource) {
+ try {
+ field.setAccessible(true);
+ return (T) field.get(resource);
+ } catch (IllegalAccessException e) {
+ throw new ScimResourceInvalidException("Schema definition is invalid", e);
+ }
+ }
+
+ @Override
+ public void set(Object resource, Object value) {
+ try {
+ field.setAccessible(true);
+ field.set(resource, value);
+ } catch (IllegalAccessException e) {
+ throw new ScimResourceInvalidException("Schema definition is invalid", e);
+ }
+ }
+
+ @Override
+ public Class<?> getType() {
+ return field.getType();
}
}
}