Add ScimRequestContext to Request.create method

Deprecate old method, new method falls back to previous

Wart, implementors must still implement the old method
diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/repository/Repository.java b/scim-core/src/main/java/org/apache/directory/scim/core/repository/Repository.java
index 27407bb..bb06e42 100644
--- a/scim-core/src/main/java/org/apache/directory/scim/core/repository/Repository.java
+++ b/scim-core/src/main/java/org/apache/directory/scim/core/repository/Repository.java
@@ -30,6 +30,7 @@
 import org.apache.directory.scim.spec.filter.PageRequest;
 import org.apache.directory.scim.spec.filter.SortRequest;
 import org.apache.directory.scim.spec.filter.attribute.AttributeReference;
+import org.apache.directory.scim.spec.filter.attribute.ScimRequestContext;
 import org.apache.directory.scim.spec.patch.PatchOperation;
 import org.apache.directory.scim.spec.resources.ScimExtension;
 import org.apache.directory.scim.spec.resources.ScimResource;
@@ -60,9 +61,25 @@
    * @return The newly created ScimResource.
    * @throws ResourceException When the ScimResource cannot be
    *         created.
+   * @deprecated call or implement create(ScimResource, ScimRequestContext)
+   * @see #create(ScimResource, ScimRequestContext)
    */
+  @Deprecated(forRemoval = true)
   T create(T resource, Set<AttributeReference> includedAttributes, Set<AttributeReference> excludedAttributes) throws ResourceException;
-  
+
+  /**
+   * Allows the SCIM server's REST implementation to create a resource via
+   * a POST to a valid end-point.
+   *
+   * @param resource The ScimResource to create and persist.
+   * @param requestContext The request context that can be used to optimize the retrieval of data.
+   * @return The newly created ScimResource.
+   * @throws ResourceException When the ScimResource cannot be created.
+   */
+  default T create(T resource, ScimRequestContext requestContext) throws ResourceException {
+    return create(resource, requestContext.getAttributeReferences(), requestContext.getExcludedAttributeReferences());
+  }
+
   /**
    * Allows the SCIM server's REST implementation to update an existing
    * resource via a PUT to a valid end-point.
diff --git a/scim-server/src/main/java/org/apache/directory/scim/server/rest/BaseResourceTypeResourceImpl.java b/scim-server/src/main/java/org/apache/directory/scim/server/rest/BaseResourceTypeResourceImpl.java
index 82eb71d..08427e5 100644
--- a/scim-server/src/main/java/org/apache/directory/scim/server/rest/BaseResourceTypeResourceImpl.java
+++ b/scim-server/src/main/java/org/apache/directory/scim/server/rest/BaseResourceTypeResourceImpl.java
@@ -175,7 +175,7 @@
     Set<AttributeReference> excludedAttributeReferences = AttributeReferenceListWrapper.getAttributeReferences(excludedAttributes);
     validateAttributes(attributeReferences, excludedAttributeReferences);
 
-    T created = repository.create(resource, attributeReferences, excludedAttributeReferences);
+    T created = repository.create(resource, new ScimRequestContext(attributeReferences, excludedAttributeReferences, null, null));
 
     EntityTag etag = fromVersion(created);
 
@@ -304,8 +304,9 @@
         ProcessingExtension processingExtension = CDI.current().select(class1).get();
         if (processingExtension instanceof AttributeFilterExtension) {
           AttributeFilterExtension attributeFilterExtension = (AttributeFilterExtension) processingExtension;
-          ScimRequestContext scimRequestContext = new ScimRequestContext(attributeReferences, excludedAttributeReferences);
-
+          ScimRequestContext scimRequestContext = new ScimRequestContext()
+              .setAttributeReferences(attributeReferences)
+              .setExcludedAttributeReferences(excludedAttributeReferences);
           try {
             resource = (T) attributeFilterExtension.filterAttributes(resource, scimRequestContext);
             log.debug("Resource now - " + resource.toString());
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 d7b5e08..d73eef6 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
@@ -43,6 +43,7 @@
 import org.apache.directory.scim.protocol.data.BulkRequest;
 import org.apache.directory.scim.protocol.data.BulkResponse;
 import org.apache.directory.scim.protocol.data.ErrorResponse;
+import org.apache.directory.scim.spec.filter.attribute.ScimRequestContext;
 import org.apache.directory.scim.spec.resources.BaseResource;
 import org.apache.directory.scim.spec.resources.ScimResource;
 import org.apache.directory.scim.spec.schema.Schema;
@@ -417,7 +418,7 @@
 
       log.debug("Creating {}", scimResource);
 
-      ScimResource newScimResource = repository.create(scimResource, Collections.emptySet(), Collections.emptySet());
+      ScimResource newScimResource = repository.create(scimResource, new ScimRequestContext());
       String bulkOperationPath = operationResult.getPath();
       String newResourceId = newScimResource.getId();
       String newResourceUri = uriInfo.getBaseUriBuilder()
diff --git a/scim-server/src/test/java/org/apache/directory/scim/server/rest/BulkResourceImplTest.java b/scim-server/src/test/java/org/apache/directory/scim/server/rest/BulkResourceImplTest.java
index 32db015..eec5cfa 100644
--- a/scim-server/src/test/java/org/apache/directory/scim/server/rest/BulkResourceImplTest.java
+++ b/scim-server/src/test/java/org/apache/directory/scim/server/rest/BulkResourceImplTest.java
@@ -30,6 +30,7 @@
 import org.apache.directory.scim.protocol.data.BulkRequest;
 import org.apache.directory.scim.protocol.data.BulkResponse;
 import org.apache.directory.scim.protocol.data.ErrorResponse;
+import org.apache.directory.scim.spec.filter.attribute.ScimRequestContext;
 import org.apache.directory.scim.spec.resources.GroupMembership;
 import org.apache.directory.scim.spec.resources.ScimGroup;
 import org.apache.directory.scim.spec.resources.ScimResource;
@@ -89,7 +90,7 @@
     user.setId("alice-id");
     when(userRepositoryInstance.get()).thenReturn(userRepository);
     repositoryRegistry.registerRepository(ScimUser.class, userRepository);
-    when(userRepository.create(any(), any(), any())).thenReturn(user);
+    when(userRepository.create(any(), any(ScimRequestContext.class))).thenReturn(user);
 
     Instance<Repository<ScimGroup>> groupProviderInstance = mock(Instance.class);
     Repository<ScimGroup> groupRepository = mock(Repository.class);
@@ -98,7 +99,7 @@
     when(groupProviderInstance.get()).thenReturn(groupRepository);
     repositoryRegistry.registerRepository(ScimGroup.class, groupRepository);
     when(groupRepository.getExtensionList()).thenReturn(Collections.emptyList());
-    when(groupRepository.create(any(), any(), any())).thenReturn(group);
+    when(groupRepository.create(any(), any(ScimRequestContext.class))).thenReturn(group);
 
     BulkResourceImpl impl = new BulkResourceImpl(schemaRegistry, repositoryRegistry);
     UriInfo uriInfo = mock(UriInfo.class);
@@ -141,8 +142,8 @@
     inOrder.verify(groupRepository, atLeast(1)).getExtensionList();
 
     // User was created before group due to calculated dependency
-    inOrder.verify(userRepository).create(alice, Collections.emptySet(), Collections.emptySet());
-    inOrder.verify(groupRepository).create(tourGuides, Collections.emptySet(), Collections.emptySet());
+    inOrder.verify(userRepository).create(alice, new ScimRequestContext());
+    inOrder.verify(groupRepository).create(tourGuides, new ScimRequestContext());
     inOrder.verifyNoMoreInteractions();
   }
 
@@ -186,7 +187,7 @@
     ScimUser userBob = new ScimUser();
     userBob.setId("bob-id");
 
-    when(userRepository.create(any(), any(), any()))
+    when(userRepository.create(any(), any(ScimRequestContext.class)))
       .thenReturn(userAlice)
       .thenThrow(new UnableToCreateResourceException(Response.Status.BAD_REQUEST, "Expected Test Exception when bob is created"));
 
diff --git a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/filter/attribute/ScimRequestContext.java b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/filter/attribute/ScimRequestContext.java
index fe4b64f..a3efd12 100644
--- a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/filter/attribute/ScimRequestContext.java
+++ b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/filter/attribute/ScimRequestContext.java
@@ -19,16 +19,29 @@
 
 package org.apache.directory.scim.spec.filter.attribute;
 
+import org.apache.directory.scim.spec.filter.PageRequest;
+import org.apache.directory.scim.spec.filter.SortRequest;
+
+import java.util.Objects;
 import java.util.Set;
 
 public class ScimRequestContext {
 
   private Set<AttributeReference> attributeReferences;
   private Set<AttributeReference> excludedAttributeReferences;
+  private PageRequest pageRequest;
+  private SortRequest sortRequest;
 
-  public ScimRequestContext(Set<AttributeReference> attributeReferences, Set<AttributeReference> excludedAttributeReferences) {
+  public ScimRequestContext() {}
+
+  public ScimRequestContext(Set<AttributeReference> attributeReferences,
+                            Set<AttributeReference> excludedAttributeReferences,
+                            PageRequest pageRequest,
+                            SortRequest sortRequest) {
     this.attributeReferences = attributeReferences;
     this.excludedAttributeReferences = excludedAttributeReferences;
+    this.pageRequest = pageRequest;
+    this.sortRequest = sortRequest;
   }
 
   public Set<AttributeReference> getAttributeReferences() {
@@ -49,37 +62,48 @@
     return this;
   }
 
-  public boolean equals(final Object o) {
-    if (o == this) return true;
-    if (!(o instanceof ScimRequestContext)) return false;
-    final ScimRequestContext other = (ScimRequestContext) o;
-    if (!other.canEqual((Object) this)) return false;
-    final Object this$attributeReferences = this.getAttributeReferences();
-    final Object other$attributeReferences = other.getAttributeReferences();
-    if (this$attributeReferences == null ? other$attributeReferences != null : !this$attributeReferences.equals(other$attributeReferences))
-      return false;
-    final Object this$excludedAttributeReferences = this.getExcludedAttributeReferences();
-    final Object other$excludedAttributeReferences = other.getExcludedAttributeReferences();
-    if (this$excludedAttributeReferences == null ? other$excludedAttributeReferences != null : !this$excludedAttributeReferences.equals(other$excludedAttributeReferences))
-      return false;
-    return true;
+  public PageRequest getPageRequest() {
+    return pageRequest;
   }
 
-  protected boolean canEqual(final Object other) {
-    return other instanceof ScimRequestContext;
+  public ScimRequestContext setPageRequest(PageRequest pageRequest) {
+    this.pageRequest = pageRequest;
+    return this;
   }
 
+  public SortRequest getSortRequest() {
+    return sortRequest;
+  }
+
+  public ScimRequestContext setSortRequest(SortRequest sortRequest) {
+    this.sortRequest = sortRequest;
+    return this;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ScimRequestContext that = (ScimRequestContext) o;
+    return Objects.equals(getAttributeReferences(), that.getAttributeReferences()) && Objects.equals(getExcludedAttributeReferences(), that.getExcludedAttributeReferences()) && Objects.equals(getPageRequest(), that.getPageRequest()) && Objects.equals(getSortRequest(), that.getSortRequest());
+  }
+
+  @Override
   public int hashCode() {
-    final int PRIME = 59;
-    int result = 1;
-    final Object $attributeReferences = this.getAttributeReferences();
-    result = result * PRIME + ($attributeReferences == null ? 43 : $attributeReferences.hashCode());
-    final Object $excludedAttributeReferences = this.getExcludedAttributeReferences();
-    result = result * PRIME + ($excludedAttributeReferences == null ? 43 : $excludedAttributeReferences.hashCode());
+    int result = Objects.hashCode(getAttributeReferences());
+    result = 31 * result + Objects.hashCode(getExcludedAttributeReferences());
+    result = 31 * result + Objects.hashCode(getPageRequest());
+    result = 31 * result + Objects.hashCode(getSortRequest());
     return result;
   }
 
+  @Override
   public String toString() {
-    return "ScimRequestContext(attributeReferences=" + this.getAttributeReferences() + ", excludedAttributeReferences=" + this.getExcludedAttributeReferences() + ")";
+    return "ScimRequestContext{" +
+      "attributeReferences=" + attributeReferences +
+      ", excludedAttributeReferences=" + excludedAttributeReferences +
+      ", pageRequest=" + pageRequest +
+      ", sortRequest=" + sortRequest +
+      '}';
   }
 }