package fr.openwide.core.jpa.more.business.difference.factory; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import com.google.common.base.Supplier; import de.danielbechler.diff.node.DiffNode; import de.danielbechler.diff.selector.CollectionItemElementSelector; import de.danielbechler.diff.selector.ElementSelector; import de.danielbechler.diff.selector.MapKeyElementSelector; import fr.openwide.core.commons.util.exception.IllegalSwitchValueException; import fr.openwide.core.commons.util.fieldpath.FieldPath; import fr.openwide.core.commons.util.rendering.IRenderer; import fr.openwide.core.jpa.more.business.difference.model.Difference; import fr.openwide.core.jpa.more.business.difference.selector.IKeyAwareSelector; import fr.openwide.core.jpa.more.business.history.model.AbstractHistoryDifference; import fr.openwide.core.jpa.more.business.history.model.atomic.HistoryDifferenceEventType; import fr.openwide.core.jpa.more.business.history.model.embeddable.HistoryDifferencePath; import fr.openwide.core.jpa.more.business.history.model.embeddable.HistoryValue; import fr.openwide.core.jpa.more.business.history.service.IHistoryValueService; import fr.openwide.core.jpa.more.rendering.service.IRendererService; public abstract class AbstractHistoryDifferenceFactory<T> implements IHistoryDifferenceFactory<T> { @Autowired private IRendererService rendererService; @Autowired private IHistoryValueService historyValueService; protected final <HD extends AbstractHistoryDifference<HD, ?>> void add(HD parent, List<HD> children) { parent.setDifferences(children); for (HD subDifference : children) { subDifference.setParentDifference(parent); } } protected final HistoryDifferenceEventType toHistoryDifferenceAction(DiffNode node) { switch (node.getState()) { case ADDED: return HistoryDifferenceEventType.ADDED; case CHANGED: return HistoryDifferenceEventType.UPDATED; case REMOVED: return HistoryDifferenceEventType.REMOVED; case UNTOUCHED: return HistoryDifferenceEventType.UNTOUCHED; default: throw new IllegalSwitchValueException(node.getState()); } } @SuppressWarnings({ "unchecked", "deprecation" }) // Ces méthodes sont les seuls moyen d'accéder aux clés... protected final HistoryValue newSelectorKeyHistoryValue(DiffNode parentNode, ElementSelector selector) { Object key; if (selector instanceof CollectionItemElementSelector) { key = ((CollectionItemElementSelector)selector).getItem(); } else if (selector instanceof MapKeyElementSelector) { key = ((MapKeyElementSelector)selector).getKey(); } else if (selector instanceof IKeyAwareSelector) { key = ((IKeyAwareSelector<?>)selector).getKey(); } else { key = null; } if (key != null) { @SuppressWarnings("rawtypes") IRenderer renderer = rendererService.findRenderer(parentNode.getValueType(), key.getClass()); return historyValueService.create(key, renderer); } else { return null; } } @SuppressWarnings({ "rawtypes" }) protected final <HD extends AbstractHistoryDifference<HD, ?>> HD newHistoryDifference(Supplier<HD> historyDifferenceSupplier, Difference<T> rootDifference, DiffNode parentNode, DiffNode currentNode, FieldPath currentNodeRelativePath, HistoryDifferenceEventType action) { final T before = rootDifference.getBefore(); final T after = rootDifference.getAfter(); HistoryValue lastSelectorKeyAuditValue = newSelectorKeyHistoryValue(parentNode, currentNode.getElementSelector()); HistoryDifferencePath historyDifferencePath = new HistoryDifferencePath(currentNodeRelativePath, lastSelectorKeyAuditValue); IRenderer renderer = rendererService.findRenderer(parentNode.getValueType(), currentNodeRelativePath, currentNode.getValueType()); HistoryValue historyValueBefore = newHistoryValue(before, currentNode, renderer); HistoryValue historyValueAfter = newHistoryValue(after, currentNode, renderer); HD historyDifference = historyDifferenceSupplier.get(); historyDifference.init(historyDifferencePath, action, historyValueBefore, historyValueAfter); return historyDifference; } @SuppressWarnings({ "rawtypes", "unchecked" }) protected final HistoryValue newHistoryValue(T root, DiffNode node, IRenderer renderer) { Object value = node.canonicalGet(root); return historyValueService.create(value, renderer); } }