package ru.hflabs.rcd.service;
import com.google.common.collect.Lists;
import ru.hflabs.rcd.model.Descriptioned;
import ru.hflabs.rcd.model.Identifying;
import ru.hflabs.rcd.model.Named;
import ru.hflabs.rcd.model.Permissioned;
import ru.hflabs.rcd.model.document.MetaField;
import java.util.Collection;
import static ru.hflabs.rcd.accessor.Accessors.*;
/**
* Класс <class>MergeServices</class> реализует вспомогательные методы для агрегирования сервисов слияния сущностей
*
* @see IMergeService
* @see IMergeService.Single
*/
public abstract class MergeServices {
/** Заглушка - возвращает всегда новый объект */
public static final IMergeService.Single<?> DUMMY = new IMergeService.Single() {
@Override
public Object merge(Object newEssence, Object oldEssence) {
return newEssence;
}
};
/** Сервис копирования идентификаторов */
public static final IMergeService.Single<? extends Identifying> IDENTIFIER = new IMergeService.Single<Identifying>() {
@Override
public Identifying merge(Identifying newEssence, Identifying oldEssence) {
return (oldEssence != null) ? injectId(newEssence, oldEssence.getId()) : newEssence;
}
};
/** Сервис копирования прав доступа */
public static final IMergeService.Single<? extends Permissioned> PERMISSION = new IMergeService.Single<Permissioned>() {
@Override
public Permissioned merge(Permissioned newEssence, Permissioned oldEssence) {
if (newEssence != null && oldEssence != null) {
newEssence.setPermissions(oldEssence.getPermissions());
}
return newEssence;
}
};
/** Сервис копирования названия */
public static final IMergeService.Single<? extends Named> NAME = new IMergeService.Single<Named>() {
@Override
public Named merge(Named newEssence, Named oldEssence) {
return (oldEssence != null) ? injectName(newEssence, oldEssence.getName()) : newEssence;
}
};
/** Сервис копирования описания */
public static final IMergeService.Single<? extends Descriptioned> DESCRIPTION = new IMergeService.Single<Descriptioned>() {
@Override
public Descriptioned merge(Descriptioned newEssence, Descriptioned oldEssence) {
return (oldEssence != null) ? injectDescription(newEssence, oldEssence.getDescription()) : newEssence;
}
};
protected MergeServices() {
// embedded constructor
}
@SuppressWarnings("unchecked")
public static <T> IMergeService.Single<T> dummy() {
return (IMergeService.Single<T>) DUMMY;
}
@SuppressWarnings("unchecked")
public static <T extends Identifying> IMergeService.Single<T> copyId() {
return (IMergeService.Single<T>) IDENTIFIER;
}
@SuppressWarnings("unchecked")
public static <T extends Permissioned> IMergeService.Single<T> copyPermission() {
return (IMergeService.Single<T>) PERMISSION;
}
@SuppressWarnings("unchecked")
public static <T extends Named> IMergeService.Single<T> copyName() {
return (IMergeService.Single<T>) NAME;
}
@SuppressWarnings("unchecked")
public static <T extends Descriptioned> IMergeService.Single<T> copyDescription() {
return (IMergeService.Single<T>) DESCRIPTION;
}
@SafeVarargs
public static <T> IMergeService.Single<T> chain(IMergeService.Single<T>... components) {
return new ChainMergeService<>(Lists.newArrayList(components));
}
/**
* Класс <class>MetaFieldMergeService</class> реслизует сервис слияния МЕТА-полей с сохранением старых значений флагов
*/
public static class MetaFieldFlagsMergeService implements IMergeService.Single<MetaField> {
@Override
public MetaField merge(MetaField newEssence, MetaField oldEssence) {
if (newEssence != null && oldEssence != null) {
newEssence.setFlags(oldEssence.getFlags());
}
return newEssence;
}
}
/**
* Класс <class>ChainMergeService</class> реализует сервис слияния, который в качестве новой сущности
* передает результат слияния предыдущего сервиса
*/
public static class ChainMergeService<T> implements IMergeService.Single<T> {
/** Коллекция сервисов */
private final Collection<IMergeService.Single<T>> components;
private ChainMergeService(Collection<IMergeService.Single<T>> components) {
this.components = components;
}
@Override
public T merge(T newEssence, T oldEssence) {
T result = newEssence;
for (IMergeService<T, T, T> service : components) {
result = service.merge(result, oldEssence);
}
return result;
}
}
}