OrphanRemovalOnUpdate.java
package org.codefilarete.stalactite.engine.configurer.onetoone;
import java.util.ArrayList;
import java.util.List;
import org.codefilarete.reflection.Accessor;
import org.codefilarete.stalactite.engine.listener.UpdateListener;
import org.codefilarete.stalactite.engine.runtime.ConfiguredPersister;
import org.codefilarete.tool.Duo;
public class OrphanRemovalOnUpdate<SRC, TRGT> implements UpdateListener<SRC> {
private final ConfiguredPersister<TRGT, ?> targetPersister;
private final Accessor<SRC, TRGT> targetAccessor;
private final Accessor<TRGT, ?> targetIdAccessor;
public OrphanRemovalOnUpdate(ConfiguredPersister<TRGT, ?> targetPersister, Accessor<SRC, TRGT> targetAccessor) {
this.targetPersister = targetPersister;
this.targetAccessor = targetAccessor;
this.targetIdAccessor = targetPersister.getMapping().getIdMapping().getIdAccessor()::getId;
}
@Override
public void afterUpdate(Iterable<? extends Duo<SRC, SRC>> payloads, boolean allColumnsStatement) {
List<TRGT> targetsToDeleteUpdate = new ArrayList<>();
payloads.forEach(duo -> {
TRGT newTarget = getTarget(duo.getLeft());
TRGT oldTarget = getTarget(duo.getRight());
// nullified relations and changed ones must be removed (orphan removal)
// TODO: one day we'll have to cover case of reused instance in same graph : one of the relation must handle it, not both,
// "else a marked instance" system must be implemented
if (oldTarget != null &&
(newTarget == null || !targetIdAccessor.get(newTarget).equals(targetIdAccessor.get(oldTarget)))) {
targetsToDeleteUpdate.add(oldTarget);
}
});
targetPersister.delete(targetsToDeleteUpdate);
}
private TRGT getTarget(SRC src) {
return src == null ? null : targetAccessor.get(src);
}
}