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/08/23 18:41:54 UTC
[directory-scimple] 02/02: Don't expose Schema.Attribute.field directly
This is an automated email from the ASF dual-hosted git repository.
bdemers pushed a commit to branch attribute-accessor
in repository https://gitbox.apache.org/repos/asf/directory-scimple.git
commit f6aa6bdcacb3c4f8bb0e6f9343db313f47b17a09
Author: Brian Demers <bd...@apache.org>
AuthorDate: Tue Aug 23 12:30:06 2022 -0400
Don't expose Schema.Attribute.field directly
The use of reflection is an implementation detail. This change moves this behind a new interface `AttributeAccessor` which provides similar functional.
In the future, implementations could use bean accessors instead of private fields directly
NOTE: the current implementation still access fields directly.
---
.../scim/server/provider/ProviderRegistry.java | 12 +-
.../scim/server/provider/UpdateRequest.java | 14 +-
.../scim/server/rest/BulkResourceImpl.java | 235 +++++++++------------
.../apache/directory/scim/spec/schema/Schema.java | 70 ++++--
4 files changed, 164 insertions(+), 167 deletions(-)
diff --git a/scim-server/src/main/java/org/apache/directory/scim/server/provider/ProviderRegistry.java b/scim-server/src/main/java/org/apache/directory/scim/server/provider/ProviderRegistry.java
index ac39bcb..1ad3f73 100644
--- a/scim-server/src/main/java/org/apache/directory/scim/server/provider/ProviderRegistry.java
+++ b/scim-server/src/main/java/org/apache/directory/scim/server/provider/ProviderRegistry.java
@@ -191,19 +191,23 @@ public class ProviderRegistry implements ScimConfiguration {
return resourceType;
}
+ public static Schema generateSchema(Class<? extends ScimResource> clazz) throws InvalidProviderException {
+ return generateBaseSchema(clazz);
+ }
+
private static Schema generateBaseSchema(Class<?> clazz) throws InvalidProviderException {
List<Field> fieldList = ReflectionUtils.getFieldsUpTo(clazz, BaseResource.class);
return generateSchema(clazz, fieldList);
}
- private static Schema generateExtensionSchema(Class<?> clazz) throws InvalidProviderException {
+ public static Schema generateExtensionSchema(Class<?> clazz) throws InvalidProviderException {
log.debug("----> In generateExtensionSchema");
return generateSchema(clazz, ReflectionUtils.getFieldsUpTo(clazz, Object.class));
}
- public static Schema generateSchema(Class<?> clazz, List<Field> fieldList) throws InvalidProviderException {
+ private static Schema generateSchema(Class<?> clazz, List<Field> fieldList) throws InvalidProviderException {
// Field [] fieldList = clazz.getDeclaredFields();
@@ -277,7 +281,7 @@ public class ProviderRegistry implements ScimConfiguration {
//TODO - Fix this to look for the two types of canonical attributes
Attribute attribute = new Attribute();
- attribute.setField(f);
+ attribute.setAccessor(Schema.AttributeAccessor.forField(f));
attribute.setName(attributeName);
attribute.setUrn(urn);
@@ -385,7 +389,7 @@ public class ProviderRegistry implements ScimConfiguration {
if (attributeIsAString) {
attribute.setScimResourceIdReference(true);
} else {
- log.warn("Field annotated with @edu.psu.swe.scim.spec.annotation.ScimResourceIdReference must be a string: {}", f);
+ log.warn("Field annotated with @ScimResourceIdReference must be a string: {}", f);
}
}
attribute.setMutability(sa.mutability());
diff --git a/scim-server/src/main/java/org/apache/directory/scim/server/provider/UpdateRequest.java b/scim-server/src/main/java/org/apache/directory/scim/server/provider/UpdateRequest.java
index 8dae3dc..856e3b4 100644
--- a/scim-server/src/main/java/org/apache/directory/scim/server/provider/UpdateRequest.java
+++ b/scim-server/src/main/java/org/apache/directory/scim/server/provider/UpdateRequest.java
@@ -54,7 +54,6 @@ import org.apache.directory.scim.spec.schema.AttributeContainer;
import org.apache.directory.scim.spec.schema.Schema;
import org.apache.directory.scim.spec.schema.Schema.Attribute;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -149,12 +148,12 @@ public class UpdateRequest<T extends ScimResource> {
private void sortMultiValuedCollections(Object obj1, Object obj2, AttributeContainer ac) throws IllegalArgumentException, IllegalAccessException {
for (Attribute attribute : ac.getAttributes()) {
- Field field = attribute.getField();
+ Schema.AttributeAccessor accessor = attribute.getAccessor();
if (attribute.isMultiValued()) {
@SuppressWarnings("unchecked")
- List<Object> collection1 = obj1 != null ? (List<Object>) field.get(obj1) : null;
+ List<Object> collection1 = obj1 != null ? (List<Object>) accessor.get(obj1) : null;
@SuppressWarnings("unchecked")
- List<Object> collection2 = obj2 != null ? (List<Object>) field.get(obj2) : null;
+ List<Object> collection2 = obj2 != null ? (List<Object>) accessor.get(obj2) : null;
Set<Object> priorities = findCommonElements(collection1, collection2);
PrioritySortingComparitor prioritySortingComparitor = new PrioritySortingComparitor(priorities);
@@ -166,8 +165,8 @@ public class UpdateRequest<T extends ScimResource> {
Collections.sort(collection2, prioritySortingComparitor);
}
} else if (attribute.getType() == Attribute.Type.COMPLEX) {
- Object nextObj1 = obj1 != null ? field.get(obj1) : null;
- Object nextObj2 = obj2 != null ? field.get(obj2) : null;
+ Object nextObj1 = obj1 != null ? accessor.get(obj1) : null;
+ Object nextObj2 = obj2 != null ? accessor.get(obj2) : null;
sortMultiValuedCollections(nextObj1, nextObj2, attribute);
}
}
@@ -595,8 +594,7 @@ public class UpdateRequest<T extends ScimResource> {
}
Attribute attribute = ac.getAttribute(attributeName);
- Field field = attribute.getField();
- return field.get(object);
+ return attribute.getAccessor().get(object);
}
}
diff --git a/scim-server/src/main/java/org/apache/directory/scim/server/rest/BulkResourceImpl.java b/scim-server/src/main/java/org/apache/directory/scim/server/rest/BulkResourceImpl.java
index f301878..0ffd13c 100644
--- a/scim-server/src/main/java/org/apache/directory/scim/server/rest/BulkResourceImpl.java
+++ b/scim-server/src/main/java/org/apache/directory/scim/server/rest/BulkResourceImpl.java
@@ -19,7 +19,6 @@
package org.apache.directory.scim.server.rest;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -502,7 +501,7 @@ public class BulkResourceImpl implements BulkResource {
@AllArgsConstructor
private static class UnresolvedComplex {
private final Object object;
- private final Field field;
+ private final Schema.AttributeAccessor accessor;
private final String bulkIdKey;
public void resolve(Map<String, BulkOperation> bulkIdKeyToOperationResult) throws UnresolvableOperationException {
@@ -512,12 +511,7 @@ public class BulkResourceImpl implements BulkResource {
if ((response == null || !(response instanceof ErrorResponse)) && resolvedResource != null) {
String resolvedId = resolvedResource.getId();
-
- try {
- this.field.set(this.object, resolvedId);
- } catch (IllegalAccessException illegalAccessException) {
- log.error("Failed to access bulkId field", illegalAccessException);
- }
+ this.accessor.set(this.object, resolvedId);
} else {
throw new UnresolvableOperationException(String.format(BULK_ID_REFERS_TO_FAILED_RESOURCE, this.bulkIdKey));
}
@@ -526,7 +520,7 @@ public class BulkResourceImpl implements BulkResource {
@AllArgsConstructor
private static abstract class UnresolvedTopLevel {
- protected final Field field;
+ protected final Schema.AttributeAccessor accessor;
public abstract void resolve(ScimResource scimResource, Map<String, BulkOperation> bulkIdKeyToOperationResult) throws UnresolvableOperationException;
}
@@ -534,8 +528,8 @@ public class BulkResourceImpl implements BulkResource {
private static class UnresolvedTopLevelBulkId extends UnresolvedTopLevel {
private final String unresolvedBulkIdKey;
- public UnresolvedTopLevelBulkId(Field field, String bulkIdKey) {
- super(field);
+ public UnresolvedTopLevelBulkId(Schema.AttributeAccessor accessor, String bulkIdKey) {
+ super(accessor);
this.unresolvedBulkIdKey = bulkIdKey;
}
@@ -548,11 +542,7 @@ public class BulkResourceImpl implements BulkResource {
if ((response == null || !(response instanceof ErrorResponse)) && resolvedResource != null) {
String resolvedId = resolvedResource.getId();
- try {
- super.field.set(scimResource, resolvedId);
- } catch (IllegalAccessException illegalAccessException) {
- log.error("Failed to access bulkId field", illegalAccessException);
- }
+ super.accessor.set(scimResource, resolvedId);
} else {
throw new UnresolvableOperationException("Bulk ID cannot be resolved because the resource it refers to had failed to be created: " + this.unresolvedBulkIdKey);
}
@@ -563,22 +553,18 @@ public class BulkResourceImpl implements BulkResource {
public final Object complex;
public final List<UnresolvedComplex> unresolveds;
- public UnresolvedTopLevelComplex(Field field, Object complex, List<UnresolvedComplex> unresolveds) {
- super(field);
+ public UnresolvedTopLevelComplex(Schema.AttributeAccessor accessor, Object complex, List<UnresolvedComplex> unresolveds) {
+ super(accessor);
this.complex = complex;
this.unresolveds = unresolveds;
}
@Override
public void resolve(ScimResource scimResource, Map<String, BulkOperation> bulkIdKeyToOperationResult) throws UnresolvableOperationException {
- try {
- for (UnresolvedComplex unresolved : this.unresolveds) {
- unresolved.resolve(bulkIdKeyToOperationResult);
- }
- this.field.set(scimResource, this.complex);
- } catch (IllegalAccessException illegalAccessException) {
- log.error("Could not resolve top level SCIM resource", illegalAccessException);
+ for (UnresolvedComplex unresolved : this.unresolveds) {
+ unresolved.resolve(bulkIdKeyToOperationResult);
}
+ this.accessor.set(scimResource, this.complex);
}
}
@@ -600,54 +586,50 @@ public class BulkResourceImpl implements BulkResource {
List<Schema.Attribute> attributes = attribute.getAttributes();
for (Schema.Attribute subAttribute : attributes) {
- Field attributeField = subAttribute.getField();
+ Schema.AttributeAccessor accessor = subAttribute.getAccessor();
- try {
- if (subAttribute.isScimResourceIdReference()) {
- // TODO - This will fail if field is a char or Character array
- String bulkIdKey = (String) attributeField.get(attributeValue);
-
- if (bulkIdKey != null && bulkIdKey.startsWith("bulkId:")) {
- log.debug("Found bulkId: {}", bulkIdKey);
- if (bulkIdKeyToOperationResult.containsKey(bulkIdKey)) {
- BulkOperation resolvedOperationResult = bulkIdKeyToOperationResult.get(bulkIdKey);
- BaseResource response = resolvedOperationResult.getResponse();
- ScimResource resolvedResource = resolvedOperationResult.getData();
-
- if ((response == null || !(response instanceof ErrorResponse)) && resolvedResource != null && resolvedResource.getId() != null) {
- String resolvedId = resolvedResource.getId();
-
- attributeField.set(attributeValue, resolvedId);
- } else {
- UnresolvedComplex unresolved = new UnresolvedComplex(attributeValue, attributeField, bulkIdKey);
-
- unresolveds.add(unresolved);
- }
+ if (subAttribute.isScimResourceIdReference()) {
+ // TODO - This will fail if field is a char or Character array
+ String bulkIdKey = accessor.get(attributeValue);
+
+ if (bulkIdKey != null && bulkIdKey.startsWith("bulkId:")) {
+ log.debug("Found bulkId: {}", bulkIdKey);
+ if (bulkIdKeyToOperationResult.containsKey(bulkIdKey)) {
+ BulkOperation resolvedOperationResult = bulkIdKeyToOperationResult.get(bulkIdKey);
+ BaseResource response = resolvedOperationResult.getResponse();
+ ScimResource resolvedResource = resolvedOperationResult.getData();
+
+ if ((response == null || !(response instanceof ErrorResponse)) && resolvedResource != null && resolvedResource.getId() != null) {
+ String resolvedId = resolvedResource.getId();
+
+ accessor.set(attributeValue, resolvedId);
} else {
- throw new UnresolvableOperationException(String.format(BULK_ID_DOES_NOT_EXIST, bulkIdKey));
+ UnresolvedComplex unresolved = new UnresolvedComplex(attributeValue, accessor, bulkIdKey);
+
+ unresolveds.add(unresolved);
}
+ } else {
+ throw new UnresolvableOperationException(String.format(BULK_ID_DOES_NOT_EXIST, bulkIdKey));
}
- } else if (subAttribute.getType() == Schema.Attribute.Type.COMPLEX) {
- Object subFieldValue = attributeField.get(attributeValue);
+ }
+ } else if (subAttribute.getType() == Schema.Attribute.Type.COMPLEX) {
+ Object subFieldValue = accessor.get(attributeValue);
- if (subFieldValue != null) {
- Class<?> subFieldClass = subFieldValue.getClass();
- boolean isCollection = Collection.class.isAssignableFrom(subFieldClass);
+ if (subFieldValue != null) {
+ Class<?> subFieldClass = subFieldValue.getClass();
+ boolean isCollection = Collection.class.isAssignableFrom(subFieldClass);
- if (isCollection || subFieldClass.isArray()) {
- @SuppressWarnings("unchecked")
- Collection<Object> subFieldValues = isCollection ? (Collection<Object>) subFieldValue : Arrays.asList((Object[]) subFieldValue);
+ if (isCollection || subFieldClass.isArray()) {
+ @SuppressWarnings("unchecked")
+ Collection<Object> subFieldValues = isCollection ? (Collection<Object>) subFieldValue : Arrays.asList((Object[]) subFieldValue);
- for (Object subArrayFieldValue : subFieldValues) {
- resolveAttribute(unresolveds, subArrayFieldValue, subAttribute, bulkIdKeyToOperationResult);
- }
- } else {
- resolveAttribute(unresolveds, subFieldValue, subAttribute, bulkIdKeyToOperationResult);
+ for (Object subArrayFieldValue : subFieldValues) {
+ resolveAttribute(unresolveds, subArrayFieldValue, subAttribute, bulkIdKeyToOperationResult);
}
+ } else {
+ resolveAttribute(unresolveds, subFieldValue, subAttribute, bulkIdKeyToOperationResult);
}
}
- } catch (IllegalAccessException illegalAccessException) {
- log.error("Could not resolve bulkId within ScimResource attribute", illegalAccessException);
}
}
log.debug("Resolved attribute had {} unresolved fields", unresolveds.size());
@@ -671,61 +653,57 @@ public class BulkResourceImpl implements BulkResource {
List<UnresolvedTopLevel> unresolvedTopLevels = new ArrayList<>();
for (Schema.Attribute attribute : schema.getAttributes()) {
- Field attributeField = attribute.getField();
+ Schema.AttributeAccessor accessor = attribute.getAccessor();
- try {
- if (attribute.isScimResourceIdReference()) {
- String bulkIdKey = (String) attributeField.get(scimResource);
+ if (attribute.isScimResourceIdReference()) {
+ String bulkIdKey = accessor.get(scimResource);
- if (bulkIdKey != null && bulkIdKey.startsWith("bulkId:")) {
- if (bulkIdKeyToOperationResult.containsKey(bulkIdKey)) {
- BulkOperation resolvedOperationResult = bulkIdKeyToOperationResult.get(bulkIdKey);
- BaseResource response = resolvedOperationResult.getResponse();
- ScimResource resolvedResource = resolvedOperationResult.getData();
+ if (bulkIdKey != null && bulkIdKey.startsWith("bulkId:")) {
+ if (bulkIdKeyToOperationResult.containsKey(bulkIdKey)) {
+ BulkOperation resolvedOperationResult = bulkIdKeyToOperationResult.get(bulkIdKey);
+ BaseResource response = resolvedOperationResult.getResponse();
+ ScimResource resolvedResource = resolvedOperationResult.getData();
- if ((response == null || !(response instanceof ErrorResponse)) && resolvedResource != null) {
- String resolvedId = resolvedResource.getId();
+ if ((response == null || !(response instanceof ErrorResponse)) && resolvedResource != null) {
+ String resolvedId = resolvedResource.getId();
- attributeField.set(scimResource, resolvedId);
- } else {
- UnresolvedTopLevel unresolved = new UnresolvedTopLevelBulkId(attributeField, bulkIdKey);
-
- attributeField.set(scimResource, null);
- unresolvedTopLevels.add(unresolved);
- }
+ accessor.set(scimResource, resolvedId);
} else {
- throw new UnresolvableOperationException(String.format(BULK_ID_DOES_NOT_EXIST, bulkIdKey));
+ UnresolvedTopLevel unresolved = new UnresolvedTopLevelBulkId(accessor, bulkIdKey);
+
+ accessor.set(scimResource, null);
+ unresolvedTopLevels.add(unresolved);
}
+ } else {
+ throw new UnresolvableOperationException(String.format(BULK_ID_DOES_NOT_EXIST, bulkIdKey));
}
- } else if (attribute.getType() == Schema.Attribute.Type.COMPLEX) {
- Object attributeFieldValue = attributeField.get(scimResource);
+ }
+ } else if (attribute.getType() == Schema.Attribute.Type.COMPLEX) {
+ Object attributeFieldValue = accessor.get(scimResource);
- if (attributeFieldValue != null) {
- List<UnresolvedComplex> subUnresolveds = new ArrayList<>();
- Class<?> subFieldClass = attributeFieldValue.getClass();
- boolean isCollection = Collection.class.isAssignableFrom(subFieldClass);
+ if (attributeFieldValue != null) {
+ List<UnresolvedComplex> subUnresolveds = new ArrayList<>();
+ Class<?> subFieldClass = attributeFieldValue.getClass();
+ boolean isCollection = Collection.class.isAssignableFrom(subFieldClass);
- if (isCollection || subFieldClass.isArray()) {
- @SuppressWarnings("unchecked")
- Collection<Object> subFieldValues = isCollection ? (Collection<Object>) attributeFieldValue : Arrays.asList((Object[]) attributeFieldValue);
+ if (isCollection || subFieldClass.isArray()) {
+ @SuppressWarnings("unchecked")
+ Collection<Object> subFieldValues = isCollection ? (Collection<Object>) attributeFieldValue : Arrays.asList((Object[]) attributeFieldValue);
- for (Object subArrayFieldValue : subFieldValues) {
- resolveAttribute(subUnresolveds, subArrayFieldValue, attribute, bulkIdKeyToOperationResult);
- }
- } else {
- resolveAttribute(subUnresolveds, attributeFieldValue, attribute, bulkIdKeyToOperationResult);
+ for (Object subArrayFieldValue : subFieldValues) {
+ resolveAttribute(subUnresolveds, subArrayFieldValue, attribute, bulkIdKeyToOperationResult);
}
+ } else {
+ resolveAttribute(subUnresolveds, attributeFieldValue, attribute, bulkIdKeyToOperationResult);
+ }
- if (subUnresolveds.size() > 0) {
- UnresolvedTopLevel unresolved = new UnresolvedTopLevelComplex(attributeField, attributeFieldValue, subUnresolveds);
+ if (subUnresolveds.size() > 0) {
+ UnresolvedTopLevel unresolved = new UnresolvedTopLevelComplex(accessor, attributeFieldValue, subUnresolveds);
- attributeField.set(scimResource, null);
- unresolvedTopLevels.add(unresolved);
- }
+ accessor.set(scimResource, null);
+ unresolvedTopLevels.add(unresolved);
}
}
- } catch (IllegalAccessException illegalAccessException) {
- log.error("Failed to access a ScimResource ID reference field to resolve it", illegalAccessException);
}
}
if (unresolvedTopLevels.size() > 0) {
@@ -781,39 +759,32 @@ public class BulkResourceImpl implements BulkResource {
private static void generateReverseDependenciesGraph(Map<String, Set<String>> reverseDependenciesGraph, String dependentBulkId, Object scimObject, List<Schema.Attribute> scimObjectAttributes) {
for (Schema.Attribute scimObjectAttribute : scimObjectAttributes)
- try {
- if (scimObjectAttribute.isScimResourceIdReference()) {
- String reference = (String) scimObjectAttribute.getField()
- .get(scimObject);
-
- if (reference != null && reference.startsWith("bulkId:")) {
- Set<String> dependents = reverseDependenciesGraph.computeIfAbsent(reference, (unused) -> new HashSet<>());
+ if (scimObjectAttribute.isScimResourceIdReference()) {
+ String reference = scimObjectAttribute.getAccessor().get(scimObject);
- dependents.add("bulkId:" + dependentBulkId);
- }
- } else if (scimObjectAttribute.isMultiValued()) { // all multiValueds
- // are COMPLEX, not
- // all COMPLEXES are
- // multiValued
- Object attributeObject = scimObjectAttribute.getField()
- .get(scimObject);
- Class<?> attributeObjectClass = attributeObject.getClass();
- boolean isCollection = Collection.class.isAssignableFrom(attributeObjectClass);
- Collection<?> attributeValues = isCollection ? (Collection<?>) attributeObject : Arrays.asList(attributeObject);
- List<Schema.Attribute> subAttributes = scimObjectAttribute.getAttributes();
-
- for (Object attributeValue : attributeValues) {
- generateReverseDependenciesGraph(reverseDependenciesGraph, dependentBulkId, attributeValue, subAttributes);
- }
- } else if (scimObjectAttribute.getType() == Schema.Attribute.Type.COMPLEX) {
- Object attributeValue = scimObjectAttribute.getField()
- .get(scimObject);
- List<Schema.Attribute> subAttributes = scimObjectAttribute.getAttributes();
+ if (reference != null && reference.startsWith("bulkId:")) {
+ Set<String> dependents = reverseDependenciesGraph.computeIfAbsent(reference, (unused) -> new HashSet<>());
+ dependents.add("bulkId:" + dependentBulkId);
+ }
+ } else if (scimObjectAttribute.isMultiValued()) { // all multiValueds
+ // are COMPLEX, not
+ // all COMPLEXES are
+ // multiValued
+ Object attributeObject = scimObjectAttribute.getAccessor().get(scimObject);
+ Class<?> attributeObjectClass = attributeObject.getClass();
+ boolean isCollection = Collection.class.isAssignableFrom(attributeObjectClass);
+ Collection<?> attributeValues = isCollection ? (Collection<?>) attributeObject : Arrays.asList(attributeObject);
+ List<Schema.Attribute> subAttributes = scimObjectAttribute.getAttributes();
+
+ for (Object attributeValue : attributeValues) {
generateReverseDependenciesGraph(reverseDependenciesGraph, dependentBulkId, attributeValue, subAttributes);
}
- } catch (IllegalAccessException illegalAccessException) {
- log.error("Resolving reverse dependencies", illegalAccessException);
+ } else if (scimObjectAttribute.getType() == Schema.Attribute.Type.COMPLEX) {
+ Object attributeValue = scimObjectAttribute.getAccessor().get(scimObject);
+ List<Schema.Attribute> subAttributes = scimObjectAttribute.getAttributes();
+
+ generateReverseDependenciesGraph(reverseDependenciesGraph, dependentBulkId, attributeValue, subAttributes);
}
}
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 7844550..e13852b 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
@@ -19,34 +19,21 @@
package org.apache.directory.scim.spec.schema;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
-import jakarta.xml.bind.annotation.XmlAccessType;
-import jakarta.xml.bind.annotation.XmlAccessorType;
-import jakarta.xml.bind.annotation.XmlElement;
-import jakarta.xml.bind.annotation.XmlElementWrapper;
-import jakarta.xml.bind.annotation.XmlEnum;
-import jakarta.xml.bind.annotation.XmlEnumValue;
-import jakarta.xml.bind.annotation.XmlRootElement;
-import jakarta.xml.bind.annotation.XmlType;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.directory.scim.spec.validator.Urn;
+import jakarta.xml.bind.annotation.*;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
+import org.apache.directory.scim.spec.exception.ScimResourceInvalidException;
+import org.apache.directory.scim.spec.validator.Urn;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Field;
+import java.util.*;
/**
* Defines the structure of the SCIM schemas as defined by section 7 of the SCIM
@@ -163,8 +150,8 @@ public class Schema implements AttributeContainer {
@XmlElement
List<String> referenceTypes;
-
- Field field;
+
+ AttributeAccessor accessor;
private boolean scimResourceIdReference;
@@ -256,4 +243,41 @@ public class Schema implements AttributeContainer {
}
return attributeNamesMap.get(name.toLowerCase());
}
+
+ public interface AttributeAccessor {
+ <T> T get(Object resource);
+
+ void set(Object resource, Object value);
+
+ 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);
+ }
+ }
+
+ @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();
+ }
+ };
+ }
+ }
}