private OperationContainer ParseForCreateOrUpdateResourceOperation(AtomicOperationObject operation, OperationKind kind) { ResourceObject resourceObject = GetRequiredSingleDataForResourceOperation(operation); AssertElementHasType(resourceObject, "data"); AssertElementHasIdOrLid(resourceObject, "data", kind != OperationKind.CreateResource); ResourceContext primaryResourceContext = GetExistingResourceContext(resourceObject.Type); AssertCompatibleId(resourceObject, primaryResourceContext.IdentityType); if (operation.Ref != null) { // For resource update, 'ref' is optional. But when specified, it must match with 'data'. AssertElementHasType(operation.Ref, "ref"); AssertElementHasIdOrLid(operation.Ref, "ref", true); ResourceContext resourceContextInRef = GetExistingResourceContext(operation.Ref.Type); if (resourceContextInRef != primaryResourceContext) { throw new JsonApiSerializationException("Resource type mismatch between 'ref.type' and 'data.type' element.", $"Expected resource of type '{resourceContextInRef.PublicName}' in 'data.type', instead of '{primaryResourceContext.PublicName}'.", atomicOperationIndex: AtomicOperationIndex); } AssertSameIdentityInRefData(operation, resourceObject); } var request = new JsonApiRequest { Kind = EndpointKind.AtomicOperations, #pragma warning disable CS0618 // Type or member is obsolete BasePath = _request.BasePath, #pragma warning restore CS0618 // Type or member is obsolete PrimaryResource = primaryResourceContext, OperationKind = kind }; _request.CopyFrom(request); IIdentifiable primaryResource = ParseResourceObject(operation.SingleData); _resourceDefinitionAccessor.OnDeserialize(primaryResource); request.PrimaryId = primaryResource.StringId; _request.CopyFrom(request); var targetedFields = new TargetedFields { Attributes = _targetedFields.Attributes.ToHashSet(), Relationships = _targetedFields.Relationships.ToHashSet() }; AssertResourceIdIsNotTargeted(targetedFields); return(new OperationContainer(kind, primaryResource, targetedFields, request)); }
private OperationContainer ParseForRelationshipOperation(AtomicOperationObject operation, OperationKind kind, bool requireToMany) { AssertElementHasType(operation.Ref, "ref"); AssertElementHasIdOrLid(operation.Ref, "ref", true); var primaryResourceContext = GetExistingResourceContext(operation.Ref.Type); AssertCompatibleId(operation.Ref, primaryResourceContext.IdentityType); var primaryResource = ResourceFactory.CreateInstance(primaryResourceContext.ResourceType); primaryResource.StringId = operation.Ref.Id; primaryResource.LocalId = operation.Ref.Lid; var relationship = GetExistingRelationship(operation.Ref, primaryResourceContext); if (requireToMany && relationship is HasOneAttribute) { throw new JsonApiSerializationException( $"Only to-many relationships can be targeted in '{operation.Code.ToString().Camelize()}' operations.", $"Relationship '{operation.Ref.Relationship}' must be a to-many relationship.", atomicOperationIndex: AtomicOperationIndex); } var secondaryResourceContext = ResourceContextProvider.GetResourceContext(relationship.RightType); var request = new JsonApiRequest { Kind = EndpointKind.AtomicOperations, BasePath = _request.BasePath, PrimaryId = primaryResource.StringId, PrimaryResource = primaryResourceContext, SecondaryResource = secondaryResourceContext, Relationship = relationship, IsCollection = relationship is HasManyAttribute, OperationKind = kind }; _request.CopyFrom(request); _targetedFields.Relationships.Add(relationship); ParseDataForRelationship(relationship, secondaryResourceContext, operation, primaryResource); var targetedFields = new TargetedFields { Attributes = _targetedFields.Attributes.ToHashSet(), Relationships = _targetedFields.Relationships.ToHashSet() }; return(new OperationContainer(kind, primaryResource, targetedFields, request)); }