Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
*
* @param operation the patch request operation to resolve
* @param resourceType the definition of the resource that is being patched
* @return the list of bulkId references if any.
*/
private List getBulkIdComplexNodesWithPath(PatchRequestOperation operation,
ResourceType resourceType)
{
AttributePathRoot pathRoot = RequestUtils.parsePatchPath(resourceType, operation.getPath().get());
SchemaAttribute schemaAttribute = pathRoot.getSchemaAttribute();
boolean isValueAttribute = AttributeNames.RFC7643.VALUE.equals(schemaAttribute.getName());
// means the patch operation path is e.g. enterpriseUser.manager
boolean isComplexAttributeBulkCandidate = schemaAttribute.isComplexBulkCandidate();
// means the patch operation path is e.g. enterpriseUser.manager.value
boolean isValueAttributeBulkCandidate = isValueAttribute && schemaAttribute.getParent() != null
&& schemaAttribute.getParent().isComplexBulkCandidate();
if (isComplexAttributeBulkCandidate || isValueAttributeBulkCandidate)
{
return resolveComplexAttributePathReference(operation);
}
else
{
return Collections.emptyList();
}
}
/**
* this method will resolve a bulkId reference within a patch request operation to a complex attribute that
* looks like this:
*
*
*
* @param operation the patch request operation
* @return a list of all found values if value attribute would contain a multivalued complex type
* representation otherwise a list with a single entry will be returned or an empty list if no bulkId
* reference was present
*/
private List resolveComplexAttributePathReference(PatchRequestOperation operation)
{
List bulkIdReferenceWrappers = new ArrayList<>();
List values = operation.getValues();
for ( int i = 0 ; i < values.size() ; i++ )
{
String operationValue = values.get(i);
boolean containsBulkIdReference = StringUtils.contains(operationValue,
String.format("%s:", AttributeNames.RFC7643.BULK_ID));
if (containsBulkIdReference)
{
BulkIdReferenceWrapper wrapper = new BulkIdReferencePatchNodeWrapper(operation, operationValue, i);
checkForBulkIdReferenceValidity(String.format("%s:%s", AttributeNames.RFC7643.BULK_ID, wrapper.getBulkId()));
bulkIdReferenceWrappers.add(wrapper);
}
}
return bulkIdReferenceWrappers;
}
/**
* will get the bulkIds from the resource itself. If a patch request does not contain a path-attribute, the
* value node is expected to contain a single element that represents the resource itself e.g. a User
* representation
*
* @param operation the patch request operation
* @return the list of found bulkId references
*/
private List getBulkIdComplexNodesFromResource(PatchRequestOperation operation)
{
ArrayNode valueNode = operation.getValueNode().orElse(null);
if (valueNode == null || valueNode.size() != 1)
{
if (valueNode != null && valueNode.size() > 1)
{
log.debug("Found error in patch request during bulkId reference resolving. "
+ "Too many value nodes are present in patch-request without a path-attribute. "
+ "The value node must be represented by the resource itself. @see RFC7644#3.5.2.1 - 3.5.2.3.");
}
return Collections.emptyList();
}
BulkIdResolverResource bulkIdResolverResource = new BulkIdResolverResource(null, uriInfos,
(ObjectNode)valueNode.get(0));
bulkIdResolverResource.findAllBulkIdReferences();
return bulkIdResolverResource.getComplexBulkIdNodes();
}
/**
* will gather all present simple nodes that represent a reference to a specific resource-type. The
* attribute-definition of such a node must look like this:
*
*
*
* @return the bulkId nodes that have a direct reference to another resource and are not bound to a complex
* type
*/
@Override
protected List getDirectBulkIdNodes()
{
List bulkIdReferenceWrapperList = new ArrayList<>();
for ( PatchRequestOperation operation : resource.getOperations() )
{
boolean isAddOrReplaceOperation = PatchOp.ADD.equals(operation.getOp())
|| PatchOp.REPLACE.equals(operation.getOp());
if (isAddOrReplaceOperation)
{
if (operation.getPath().isPresent())
{
List referenceWrapperList = getSimpleBulkIdNodeFromPathRefNode(operation,
uriInfos.getResourceType());
bulkIdReferenceWrapperList.addAll(referenceWrapperList);
}
else
{
List referenceWrapperList = getBulkIdSimpleNodesFromResource(operation);
bulkIdReferenceWrapperList.addAll(referenceWrapperList);
}
} // do nothing in else case. It is not possible to have bulkId references in remove operations
}
return bulkIdReferenceWrapperList;
}
/**
* tries to get the bulkId references from the given patch operation if no path is present
*
* @param operation the patch operation to search for bulkId references
* @return the found bulkId references
*/
private List getBulkIdSimpleNodesFromResource(PatchRequestOperation operation)
{
ArrayNode valueNode = operation.getValueNode().orElse(null);
if (valueNode == null || valueNode.size() != 1)
{
if (valueNode != null && valueNode.size() > 1)
{
log.debug("Found error in patch request during bulkId reference resolving. "
+ "Too many value nodes are present in patch-request without a path-attribute. "
+ "The value node must be represented by the resource itself. @see RFC7644#3.5.2.1 - 3.5.2.3.");
}
return Collections.emptyList();
}
BulkIdResolverResource bulkIdResolverResource = new BulkIdResolverResource(null, uriInfos,
(ObjectNode)valueNode.get(0));
bulkIdResolverResource.findAllBulkIdReferences();
return bulkIdResolverResource.getDirectBulkIdNodes();
}
/**
* this method will extract simple bulkId references from a patch operation that are introduced by the custom
* feature, have a path-attribute and that might look like this:
*
*
*
* @param operation the patch operation from which the value must be extracted
* @param resourceType the resources definition
* @return the list of bulkId references if any.
*/
private List getSimpleBulkIdNodeFromPathRefNode(PatchRequestOperation operation,
ResourceType resourceType)
{
ArrayNode valueNodeArray = operation.getValueNode().orElse(null);
if (valueNodeArray == null)
{
// should only happen with erroneously crafted requests
return Collections.emptyList();
}
AttributePathRoot pathRoot = RequestUtils.parsePatchPath(resourceType, operation.getPath().get());
SchemaAttribute schemaAttribute = pathRoot.getSchemaAttribute();
boolean isBulkIdCandidate = schemaAttribute.isSimpleValueBulkCandidate();
if (!isBulkIdCandidate && Type.COMPLEX.equals(schemaAttribute.getType()))
{
return getBulkIdReferencesFromComplexTypes(operation, schemaAttribute);
}
else if (!isBulkIdCandidate)
{
return Collections.emptyList();
}
return getBulkIdReferencesOnSimpleTypes(operation);
}
/**
* gets simple bulkId references from complex nodes that might contain bulkId reference nodes
*
* @param operation the patch operation to check for bulkId references
* @param schemaAttribute the current attributes definition
* @return the found bulkId references
*/
private List getBulkIdReferencesFromComplexTypes(PatchRequestOperation operation,
SchemaAttribute schemaAttribute)
{
List bulkIdReferenceWrappers = new ArrayList<>();
ArrayNode valueNodeArray = operation.getValueNode().orElse(null);
List bulkIdAttributes = schemaAttribute.getSubAttributes()
.stream()
.filter(SchemaAttribute::isSimpleValueBulkCandidate)
.collect(Collectors.toList());
if (bulkIdAttributes.isEmpty())
{
return Collections.emptyList();
}
for ( JsonNode complexNode : valueNodeArray )
{
if (!containsBulkIdReference(complexNode))
{
continue;
}
for ( SchemaAttribute subAttribute : bulkIdAttributes )
{
JsonNode node = complexNode.get(subAttribute.getName());
if (node == null)
{
continue;
}
if (node.isArray())
{
for ( int i = 0 ; i < node.size() ; i++ )
{
JsonNode arrayIndexNode = node.get(i);
if (containsBulkIdReference(arrayIndexNode))
{
bulkIdReferenceWrappers.add(new BulkIdReferenceArrayWrapper((ArrayNode)node, i));
}
}
}
else
{
if (containsBulkIdReference(node))
{
bulkIdReferenceWrappers.add(new BulkIdReferenceResourceWrapper(complexNode, node, subAttribute));
}
}
}
}
return bulkIdReferenceWrappers;
}
/**
* will search for bulkIds on simple types within the value-array of the patch operation. The path is expected
* to point directly on a leaf-attribute that is a simple bulkId reference
*
* @param operation the patch operation to search for bulkId references
* @return the list of found bulkId references
*/
private List getBulkIdReferencesOnSimpleTypes(PatchRequestOperation operation)
{
List bulkIdReferenceWrappers = new ArrayList<>();
// since a simple bulkId candidate will always be a leaf-node we do not need to look at the parents
ArrayNode valueNodeArray = operation.getValueNode().orElse(null);
for ( int i = 0 ; i < valueNodeArray.size() ; i++ )
{
JsonNode valueNode = valueNodeArray.get(i);
if (valueNode.isTextual() && containsBulkIdReference(valueNode))
{
String bulkIdReference = valueNode.textValue();
checkForBulkIdReferenceValidity(bulkIdReference);
bulkIdReferenceWrappers.add(new BulkIdReferenceArrayWrapper(valueNodeArray, i));
}
}
return bulkIdReferenceWrappers;
}
}