-
-
Notifications
You must be signed in to change notification settings - Fork 259
Expand file tree
/
Copy pathParseRelationOperation.cs
More file actions
129 lines (105 loc) · 5.09 KB
/
ParseRelationOperation.cs
File metadata and controls
129 lines (105 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Parse.Abstractions.Infrastructure;
using Parse.Abstractions.Infrastructure.Control;
using Parse.Abstractions.Platform.Objects;
using Parse.Infrastructure.Data;
namespace Parse.Infrastructure.Control;
public class ParseRelationOperation : IParseFieldOperation
{
IList<string> Additions { get; }
IList<string> Removals { get; }
IParseObjectClassController ClassController { get; }
ParseRelationOperation(IParseObjectClassController classController) => ClassController = classController;
ParseRelationOperation(IParseObjectClassController classController, IEnumerable<string> adds, IEnumerable<string> removes, string targetClassName) : this(classController)
{
TargetClassName = targetClassName;
Additions = new ReadOnlyCollection<string>(adds.ToList());
Removals = new ReadOnlyCollection<string>(removes.ToList());
}
public ParseRelationOperation(IParseObjectClassController classController, IEnumerable<ParseObject> adds, IEnumerable<ParseObject> removes) : this(classController)
{
adds ??= new ParseObject[0];
removes ??= new ParseObject[0];
TargetClassName = adds.Concat(removes).Select(entity => entity.ClassName).FirstOrDefault();
Additions = new ReadOnlyCollection<string>(GetIdsFromObjects(adds).ToList());
Removals = new ReadOnlyCollection<string>(GetIdsFromObjects(removes).ToList());
}
public IParseFieldOperation MergeWithPrevious(IParseFieldOperation previous)
{
return previous switch
{
null => this,
ParseDeleteOperation { } => throw new InvalidOperationException("You can't modify a relation after deleting it."),
ParseRelationOperation { } other when other.TargetClassName != TargetClassName => throw new InvalidOperationException($"Related object must be of class {other.TargetClassName}, but {TargetClassName} was passed in."),
ParseRelationOperation { ClassController: var classController } other => new ParseRelationOperation(classController, Additions.Union(other.Additions.Except(Removals)).ToList(), Removals.Union(other.Removals.Except(Additions)).ToList(), TargetClassName),
_ => throw new InvalidOperationException("Operation is invalid after previous operation.")
};
}
public object Apply(object oldValue, string key)
{
if (Additions.Count == 0 && Removals.Count == 0)
{
return default;
}
if (oldValue == null)
{
var val = ClassController.CreateRelation(null, key, TargetClassName);
Value = val;
return val;
}
if (oldValue is ParseRelationBase oldRelation)
{
if (oldRelation.TargetClassName != null && oldRelation.TargetClassName != TargetClassName)
{
throw new InvalidOperationException($"Related object must be a {oldRelation.TargetClassName}, but a {TargetClassName} was passed in.");
}
Value = oldRelation;
oldRelation.TargetClassName = TargetClassName;
return oldRelation;
}
throw new InvalidOperationException("Operation is invalid after previous operation.");
}
public object Value { get; private set; }
public string TargetClassName { get; }
IEnumerable<string> GetIdsFromObjects(IEnumerable<ParseObject> objects)
{
foreach (ParseObject entity in objects)
{
if (entity.ObjectId is null)
{
throw new ArgumentException("You can't add an unsaved ParseObject to a relation.");
}
if (entity.ClassName != TargetClassName)
{
throw new ArgumentException($"Tried to create a ParseRelation with 2 different types: {TargetClassName} and {entity.ClassName}");
}
}
return objects.Select(entity => entity.ObjectId).Distinct();
}
public IDictionary<string, object> ConvertToJSON(IServiceHub serviceHub = null)
{
List<object> additions = Additions.Select(id => PointerOrLocalIdEncoder.Instance.Encode(ClassController.CreateObjectWithoutData(TargetClassName, id, serviceHub), serviceHub)).ToList(), removals = Removals.Select(id => PointerOrLocalIdEncoder.Instance.Encode(ClassController.CreateObjectWithoutData(TargetClassName, id, serviceHub), serviceHub)).ToList();
Dictionary<string, object> addition = additions.Count == 0 ? default : new Dictionary<string, object>
{
["__op"] = "AddRelation",
["objects"] = additions
};
Dictionary<string, object> removal = removals.Count == 0 ? default : new Dictionary<string, object>
{
["__op"] = "RemoveRelation",
["objects"] = removals
};
if (addition is { } && removal is { })
{
return new Dictionary<string, object>
{
["__op"] = "Batch",
["ops"] = new[] { addition, removal }
};
}
return addition ?? removal;
}
}