In the event that both master and child previously had an item, and the payload
of the item has changed on both ends, the payload as given in the child
-will take precedence.
+will take precedence. If both previously had an item, and it changed on only
+one end, the new value "wins".
This relationship should hold:
findAdded masterstate childstate $ lastchildstate)
++ (map (pairToFunc ModifyContent) . Map.toList $ childPayloadChanges)
masterPayloadChanges =
- Map.union (findModified childstate lastchildstate)
- (findModified childstate masterstate)
+ Map.union (findModified masterstate childstate lastchildstate)
+ (findModified masterstate childstate masterstate)
+
-- The child's payload takes precedence, so we are going to
-- calculate the changes made on the master to apply to the client,
-- then subtract out any items in the master changes that have the
-- same key.
childPayloadChanges =
- foldl (flip Map.delete) (findModified masterstate lastchildstate)
- (Map.keys (findModified childstate masterstate))
-
+ foldl (\m (k, v) -> Map.adjust (\_ -> v) k m)
+ (findModified childstate masterstate lastchildstate)
+ (Map.toList $ findModified masterstate childstate lastchildstate)
{- | Compares two SyncCollections, and returns the commands that, when
applied to the first collection, would yield the second. -}
is different in state1 than it was in lastchildstate. Returns the key and new
payload for each such item found. -}
findModified :: (Ord k, Eq v) =>
- SyncCollection k v -> SyncCollection k v -> SyncCollection k v
-findModified state1 lastchildstate =
+ SyncCollection k v -> SyncCollection k v -> SyncCollection k v -> SyncCollection k v
+findModified basestate state1 lastchildstate =
Map.mapMaybe id .
- Map.intersectionWith (\v1 v2 -> if v1 /= v2 then Just v1 else Nothing)
- state1 $ lastchildstate
+ Map.intersectionWithKey comparefunc state1 $ lastchildstate
+ where comparefunc k v1 v2 =
+ if v1 /= v2
+ then case Map.lookup k basestate of
+ Nothing -> Nothing
+ Just baseval ->
+ if baseval == v1
+ then Nothing
+ else Just v1
+ else Nothing
{- | Apply the specified changes to the given SyncCollection. Returns
a new SyncCollection with the changes applied. If changes are specified
Map.delete key collection
makeChange collection (CopyItem key val) =
Map.insert key val collection
+ makeChange collection (ModifyContent key val) =
+ Map.adjust (\_ -> val) key collection
in foldl makeChange collection commands