net.nemerosa.ontrack.model.structure.SyncPolicy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ontrack-model Show documentation
Show all versions of ontrack-model Show documentation
Ontrack module: ontrack-model
package net.nemerosa.ontrack.model.structure;
import lombok.Data;
import net.nemerosa.ontrack.model.exceptions.SyncTargetItemPresentException;
import net.nemerosa.ontrack.model.exceptions.SyncTargetItemUnknownException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* Behaviour to adopt when synchronising two lists.
*/
@Data
public class SyncPolicy {
/**
* Target already present.
*
*
* - Can be ignored
* - Can be replaced
* - Can raise an error
*
*/
private final TargetPresentPolicy targetPresentPolicy;
/**
* Unknown target.
*
*
* - Can be ignored
* - Can be deleted
* - Can raise an error
*
*/
private final UnknownTargetPolicy unknownTargetPolicy;
/**
* This Sync policy is conservative, making sure existing items in the target are kept as they were.
*/
public static final SyncPolicy COPY = new SyncPolicy(TargetPresentPolicy.IGNORE, UnknownTargetPolicy.IGNORE);
/**
* This Sync policy makes sure the source and the target are exactly aligned. Any existing item in the target
* which is not in the source will be deleted.
*/
public static final SyncPolicy SYNC = new SyncPolicy(TargetPresentPolicy.REPLACE, UnknownTargetPolicy.DELETE);
/**
* This Sync policy makes sure the source and the target common elements are synchronised. Any existing item in the
* target is kept if not existing in the source.
*/
public static final SyncPolicy SYNC_KEEP = new SyncPolicy(TargetPresentPolicy.REPLACE, UnknownTargetPolicy.IGNORE);
public static enum TargetPresentPolicy {
IGNORE,
REPLACE,
ERROR
}
public enum UnknownTargetPolicy {
IGNORE,
DELETE,
ERROR
}
public SyncResult sync(SyncConfig config) {
SyncResult result = SyncResult.empty();
// Gets the source items
Collection sourceItems = config.getSourceItems();
// Index of target items
Map targetMap = config.getTargetItems().stream().collect(
Collectors.toMap(
config::getItemId,
Function.identity()
)
);
// For each source item
for (T sourceItem : sourceItems) {
// Gets its identifier for the target items
D itemId = config.getItemId(sourceItem);
// Gets a corresponding item
T targetItem = targetMap.get(itemId);
// If present
if (targetItem != null && config.isTargetItemPresent(targetItem)) {
// This depends on the policy
switch (targetPresentPolicy) {
case IGNORE:
result.ignorePresentTarget();
break;
case REPLACE:
config.replaceTargetItem(sourceItem, targetItem);
result.replacePresentTarget();
break;
case ERROR:
default:
throw new SyncTargetItemPresentException(config.getItemType(), itemId);
}
}
// If not present, creates it
else {
config.createTargetItem(sourceItem);
result.create();
}
}
// Now that target items have been either created or updated, we need to know which ones were
// not matched with the sources
targetMap = config.getTargetItems().stream().collect(
Collectors.toMap(
config::getItemId,
Function.identity()
)
);
Collection targetIds = new HashSet<>(targetMap.keySet());
Collection sourceIds = sourceItems.stream().map(config::getItemId).collect(Collectors.toList());
targetIds.removeAll(sourceIds);
int unknownTargetNumber = targetIds.size();
if (unknownTargetNumber > 0) {
switch (unknownTargetPolicy) {
case IGNORE:
result.setUnknownTargetIgnored(unknownTargetNumber);
break;
case DELETE:
for (D targetId : targetIds) {
T targetItem = targetMap.get(targetId);
config.deleteTargetItem(targetItem);
}
result.setUnknownTargetDeleted(unknownTargetNumber);
break;
case ERROR:
default:
throw new SyncTargetItemUnknownException(config.getItemType(), targetIds);
}
}
// OK
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy