package ru.hflabs.rcd.model.change;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.Getter;
import lombok.Setter;
import ru.hflabs.rcd.model.Historical;
import ru.hflabs.util.core.Holder;
import ru.hflabs.util.core.Pair;
import ru.hflabs.util.core.collection.ArrayUtil;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Map;
/**
* Класс <class>ChangeSetBuilder</class> реализует дескриптор построения изменений сущностей
*
* @see ChangeSet
*/
@Getter
@Setter
public class HistoryBuilder<E extends Historical> {
/** Целевой класс объектов */
private final Class<E> targetClass;
/** Режим изменения объектов */
private ChangeMode changeMode;
/** Карта операций с сущностями */
private final Holder<ChangeType, ChangeSet<E>> holder;
public HistoryBuilder(Class<E> targetClass) {
this(targetClass, ChangeMode.DEFAULT);
}
public HistoryBuilder(Class<E> targetClass, ChangeMode changeMode) {
this.targetClass = targetClass;
this.holder = new Type2SetHolder();
this.changeMode = changeMode;
}
/**
* @param type тип изменений
* @return Возвращает коллекцию изменений по типу
*/
public ChangeSet<E> getChangeSet(ChangeType type) {
return holder.getValue(type);
}
/**
* @param types коллекция целевых типов изменений
* @return Возвращает коллекцию изменений
*/
public Map<ChangeType, ChangeSet<E>> getChangeSets(ChangeType... types) {
final Collection<ChangeType> targetTypes = ArrayUtil.isEmpty(types) ?
EnumSet.allOf(ChangeType.class) :
Sets.newHashSet(types);
return Maps.newHashMap(Maps.filterKeys(holder.takeSnapshot(), new Predicate<ChangeType>() {
@Override
public boolean apply(ChangeType input) {
return targetTypes.contains(input);
}
}));
}
/**
* @param types коллекция целевых типов изменений
* @return Возвращает все сущности дескриптора
*/
public Collection<E> getEssences(ChangeType... types) {
final ImmutableList.Builder<E> builder = ImmutableList.builder();
for (ChangeSet<E> changeSet : getChangeSets(types).values()) {
builder.addAll(changeSet.getChanged());
}
return builder.build();
}
/**
* Добавляет изменение
*
* @param change измерение
* @return Возвращает ссылку на сервис построения
*/
public HistoryBuilder<E> addChange(Pair<ChangeType, E> change) {
getChangeSet(change.first).appendChange(change.second);
return this;
}
/**
* Добавляет коллекцию изменений
*
* @param changeSets коллекция изменений
* @return Возвращает ссылку на сервис построения
*/
public HistoryBuilder<E> addChangeSets(Map<ChangeType, ChangeSet<E>> changeSets) {
for (Map.Entry<ChangeType, ChangeSet<E>> entry : changeSets.entrySet()) {
getChangeSet(entry.getKey()).appendChanges(entry.getValue().getChanged());
}
return this;
}
/**
* Класс <class>Type2SetHolder</class> реализует кеш операций
*
* @see Holder
*/
private class Type2SetHolder extends Holder<ChangeType, ChangeSet<E>> {
@Override
protected ChangeSet<E> createValue(ChangeType key) {
return new ChangeSet<>(targetClass, key, changeMode);
}
}
}