Skip to content

Commit

Permalink
PLANNER-1238 Don't store Supply's in moves because they can't be rebased
Browse files Browse the repository at this point in the history
  • Loading branch information
ge0ffrey committed Sep 5, 2018
1 parent 1895ad8 commit 7667daf
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 55 deletions.
Expand Up @@ -29,12 +29,22 @@
*/ */
public class ChainedChangeMove<Solution_> extends ChangeMove<Solution_> { public class ChainedChangeMove<Solution_> extends ChangeMove<Solution_> {


protected final SingletonInverseVariableSupply inverseVariableSupply; protected final Object oldTrailingEntity;
protected final Object newTrailingEntity;


public ChainedChangeMove(Object entity, GenuineVariableDescriptor<Solution_> variableDescriptor, public ChainedChangeMove(Object entity, GenuineVariableDescriptor<Solution_> variableDescriptor,
SingletonInverseVariableSupply inverseVariableSupply, Object toPlanningValue) { SingletonInverseVariableSupply inverseVariableSupply, Object toPlanningValue) {
super(entity, variableDescriptor, toPlanningValue); super(entity, variableDescriptor, toPlanningValue);
this.inverseVariableSupply = inverseVariableSupply; oldTrailingEntity = inverseVariableSupply.getInverseSingleton(entity);
newTrailingEntity = toPlanningValue == null ? null
: inverseVariableSupply.getInverseSingleton(toPlanningValue);
}

public ChainedChangeMove(Object entity, GenuineVariableDescriptor<Solution_> variableDescriptor, Object toPlanningValue,
Object oldTrailingEntity, Object newTrailingEntity) {
super(entity, variableDescriptor, toPlanningValue);
this.oldTrailingEntity = oldTrailingEntity;
this.newTrailingEntity = newTrailingEntity;
} }


// ************************************************************************ // ************************************************************************
Expand All @@ -50,15 +60,12 @@ public boolean isMoveDoable(ScoreDirector<Solution_> scoreDirector) {
@Override @Override
public ChainedChangeMove<Solution_> createUndoMove(ScoreDirector<Solution_> scoreDirector) { public ChainedChangeMove<Solution_> createUndoMove(ScoreDirector<Solution_> scoreDirector) {
Object oldValue = variableDescriptor.getValue(entity); Object oldValue = variableDescriptor.getValue(entity);
return new ChainedChangeMove<>(entity, variableDescriptor, inverseVariableSupply, oldValue); return new ChainedChangeMove<>(entity, variableDescriptor, oldValue, newTrailingEntity, oldTrailingEntity);
} }


@Override @Override
protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector) { protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector) {
Object oldValue = variableDescriptor.getValue(entity); Object oldValue = variableDescriptor.getValue(entity);
Object oldTrailingEntity = inverseVariableSupply.getInverseSingleton(entity);
Object newTrailingEntity = toPlanningValue == null ? null
: inverseVariableSupply.getInverseSingleton(toPlanningValue);
// Close the old chain // Close the old chain
if (oldTrailingEntity != null) { if (oldTrailingEntity != null) {
scoreDirector.changeVariableFacade(variableDescriptor, oldTrailingEntity, oldValue); scoreDirector.changeVariableFacade(variableDescriptor, oldTrailingEntity, oldValue);
Expand All @@ -74,8 +81,10 @@ protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector)
@Override @Override
public ChainedChangeMove<Solution_> rebase(ScoreDirector<Solution_> destinationScoreDirector) { public ChainedChangeMove<Solution_> rebase(ScoreDirector<Solution_> destinationScoreDirector) {
return new ChainedChangeMove<>(destinationScoreDirector.lookUpWorkingObject(entity), return new ChainedChangeMove<>(destinationScoreDirector.lookUpWorkingObject(entity),
variableDescriptor, inverseVariableSupply, variableDescriptor,
destinationScoreDirector.lookUpWorkingObject(toPlanningValue)); destinationScoreDirector.lookUpWorkingObject(toPlanningValue),
destinationScoreDirector.lookUpWorkingObject(oldTrailingEntity),
destinationScoreDirector.lookUpWorkingObject(newTrailingEntity));
} }


} }
Expand Up @@ -16,6 +16,7 @@


package org.optaplanner.core.impl.heuristic.selector.move.generic.chained; package org.optaplanner.core.impl.heuristic.selector.move.generic.chained;


import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;


Expand All @@ -30,12 +31,26 @@
*/ */
public class ChainedSwapMove<Solution_> extends SwapMove<Solution_> { public class ChainedSwapMove<Solution_> extends SwapMove<Solution_> {


protected final List<SingletonInverseVariableSupply> inverseVariableSupplyList; protected final List<Object> oldLeftTrailingEntityList;
protected final List<Object> oldRightTrailingEntityList;


public ChainedSwapMove(List<GenuineVariableDescriptor<Solution_>> variableDescriptorList, public ChainedSwapMove(List<GenuineVariableDescriptor<Solution_>> variableDescriptorList,
List<SingletonInverseVariableSupply> inverseVariableSupplyList, Object leftEntity, Object rightEntity) { List<SingletonInverseVariableSupply> inverseVariableSupplyList, Object leftEntity, Object rightEntity) {
super(variableDescriptorList, leftEntity, rightEntity); super(variableDescriptorList, leftEntity, rightEntity);
this.inverseVariableSupplyList = inverseVariableSupplyList; oldLeftTrailingEntityList = new ArrayList<>(inverseVariableSupplyList.size());
oldRightTrailingEntityList = new ArrayList<>(inverseVariableSupplyList.size());
for (SingletonInverseVariableSupply inverseVariableSupply : inverseVariableSupplyList) {
oldLeftTrailingEntityList.add(inverseVariableSupply.getInverseSingleton(leftEntity));
oldRightTrailingEntityList.add(inverseVariableSupply.getInverseSingleton(rightEntity));
}
}

public ChainedSwapMove(List<GenuineVariableDescriptor<Solution_>> genuineVariableDescriptors,
Object leftEntity, Object rightEntity,
List<Object> oldLeftTrailingEntityList, List<Object> oldRightTrailingEntityList) {
super(genuineVariableDescriptors, leftEntity, rightEntity);
this.oldLeftTrailingEntityList = oldLeftTrailingEntityList;
this.oldRightTrailingEntityList = oldRightTrailingEntityList;
} }


// ************************************************************************ // ************************************************************************
Expand All @@ -44,7 +59,7 @@ public ChainedSwapMove(List<GenuineVariableDescriptor<Solution_>> variableDescri


@Override @Override
public ChainedSwapMove<Solution_> createUndoMove(ScoreDirector<Solution_> scoreDirector) { public ChainedSwapMove<Solution_> createUndoMove(ScoreDirector<Solution_> scoreDirector) {
return new ChainedSwapMove<>(variableDescriptorList, inverseVariableSupplyList, rightEntity, leftEntity); return new ChainedSwapMove<>(variableDescriptorList, rightEntity, leftEntity, oldLeftTrailingEntityList, oldRightTrailingEntityList);
} }


@Override @Override
Expand All @@ -58,9 +73,8 @@ protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector)
scoreDirector.changeVariableFacade(variableDescriptor, leftEntity, oldRightValue); scoreDirector.changeVariableFacade(variableDescriptor, leftEntity, oldRightValue);
scoreDirector.changeVariableFacade(variableDescriptor, rightEntity, oldLeftValue); scoreDirector.changeVariableFacade(variableDescriptor, rightEntity, oldLeftValue);
} else { } else {
SingletonInverseVariableSupply inverseVariableSupply = inverseVariableSupplyList.get(i); Object oldLeftTrailingEntity = oldLeftTrailingEntityList.get(i);
Object oldLeftTrailingEntity = inverseVariableSupply.getInverseSingleton(leftEntity); Object oldRightTrailingEntity = oldRightTrailingEntityList.get(i);
Object oldRightTrailingEntity = inverseVariableSupply.getInverseSingleton(rightEntity);
if (oldRightValue == leftEntity) { if (oldRightValue == leftEntity) {
// Change the right entity // Change the right entity
scoreDirector.changeVariableFacade(variableDescriptor, rightEntity, oldLeftValue); scoreDirector.changeVariableFacade(variableDescriptor, rightEntity, oldLeftValue);
Expand Down Expand Up @@ -100,9 +114,11 @@ protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector)


@Override @Override
public ChainedSwapMove<Solution_> rebase(ScoreDirector<Solution_> destinationScoreDirector) { public ChainedSwapMove<Solution_> rebase(ScoreDirector<Solution_> destinationScoreDirector) {
return new ChainedSwapMove<>(variableDescriptorList, inverseVariableSupplyList, return new ChainedSwapMove<>(variableDescriptorList,
destinationScoreDirector.lookUpWorkingObject(leftEntity), destinationScoreDirector.lookUpWorkingObject(leftEntity),
destinationScoreDirector.lookUpWorkingObject(rightEntity)); destinationScoreDirector.lookUpWorkingObject(rightEntity),
rebaseList(oldLeftTrailingEntityList, destinationScoreDirector),
rebaseList(oldRightTrailingEntityList, destinationScoreDirector));
} }


} }
Expand Up @@ -36,15 +36,28 @@ public class SubChainChangeMove<Solution_> extends AbstractMove<Solution_> {


protected final SubChain subChain; protected final SubChain subChain;
protected final GenuineVariableDescriptor<Solution_> variableDescriptor; protected final GenuineVariableDescriptor<Solution_> variableDescriptor;
protected final SingletonInverseVariableSupply inverseVariableSupply;
protected final Object toPlanningValue; protected final Object toPlanningValue;


protected final Object oldTrailingLastEntity;
protected final Object newTrailingEntity;

public SubChainChangeMove(SubChain subChain, GenuineVariableDescriptor<Solution_> variableDescriptor, public SubChainChangeMove(SubChain subChain, GenuineVariableDescriptor<Solution_> variableDescriptor,
SingletonInverseVariableSupply inverseVariableSupply, Object toPlanningValue) { SingletonInverseVariableSupply inverseVariableSupply, Object toPlanningValue) {
this.subChain = subChain; this.subChain = subChain;
this.variableDescriptor = variableDescriptor; this.variableDescriptor = variableDescriptor;
this.inverseVariableSupply = inverseVariableSupply;
this.toPlanningValue = toPlanningValue; this.toPlanningValue = toPlanningValue;
oldTrailingLastEntity = inverseVariableSupply.getInverseSingleton(subChain.getLastEntity());
newTrailingEntity = toPlanningValue == null ? null
: inverseVariableSupply.getInverseSingleton(toPlanningValue);
}

public SubChainChangeMove(SubChain subChain, GenuineVariableDescriptor<Solution_> variableDescriptor,
Object toPlanningValue, Object oldTrailingLastEntity, Object newTrailingEntity) {
this.subChain = subChain;
this.variableDescriptor = variableDescriptor;
this.toPlanningValue = toPlanningValue;
this.oldTrailingLastEntity = oldTrailingLastEntity;
this.newTrailingEntity = newTrailingEntity;
} }


public String getVariableName() { public String getVariableName() {
Expand Down Expand Up @@ -75,17 +88,14 @@ public boolean isMoveDoable(ScoreDirector<Solution_> scoreDirector) {
@Override @Override
public SubChainChangeMove<Solution_> createUndoMove(ScoreDirector<Solution_> scoreDirector) { public SubChainChangeMove<Solution_> createUndoMove(ScoreDirector<Solution_> scoreDirector) {
Object oldFirstValue = variableDescriptor.getValue(subChain.getFirstEntity()); Object oldFirstValue = variableDescriptor.getValue(subChain.getFirstEntity());
return new SubChainChangeMove<>(subChain, variableDescriptor, inverseVariableSupply, oldFirstValue); return new SubChainChangeMove<>(subChain, variableDescriptor, oldFirstValue, newTrailingEntity, oldTrailingLastEntity);
} }


@Override @Override
protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector) { protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector) {
Object firstEntity = subChain.getFirstEntity(); Object firstEntity = subChain.getFirstEntity();
Object lastEntity = subChain.getLastEntity(); Object lastEntity = subChain.getLastEntity();
Object oldFirstValue = variableDescriptor.getValue(firstEntity); Object oldFirstValue = variableDescriptor.getValue(firstEntity);
Object oldTrailingLastEntity = inverseVariableSupply.getInverseSingleton(lastEntity);
Object newTrailingEntity = toPlanningValue == null ? null
: inverseVariableSupply.getInverseSingleton(toPlanningValue);
// Close the old chain // Close the old chain
if (oldTrailingLastEntity != null) { if (oldTrailingLastEntity != null) {
scoreDirector.changeVariableFacade(variableDescriptor, oldTrailingLastEntity, oldFirstValue); scoreDirector.changeVariableFacade(variableDescriptor, oldTrailingLastEntity, oldFirstValue);
Expand All @@ -101,8 +111,10 @@ protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector)
@Override @Override
public SubChainChangeMove<Solution_> rebase(ScoreDirector<Solution_> destinationScoreDirector) { public SubChainChangeMove<Solution_> rebase(ScoreDirector<Solution_> destinationScoreDirector) {
return new SubChainChangeMove<>(subChain.rebase(destinationScoreDirector), return new SubChainChangeMove<>(subChain.rebase(destinationScoreDirector),
variableDescriptor, inverseVariableSupply, variableDescriptor,
destinationScoreDirector.lookUpWorkingObject(toPlanningValue)); destinationScoreDirector.lookUpWorkingObject(toPlanningValue),
destinationScoreDirector.lookUpWorkingObject(oldTrailingLastEntity),
destinationScoreDirector.lookUpWorkingObject(newTrailingEntity));
} }


// ************************************************************************ // ************************************************************************
Expand Down
Expand Up @@ -36,15 +36,28 @@ public class SubChainReversingChangeMove<Solution_> extends AbstractMove<Solutio


protected final SubChain subChain; protected final SubChain subChain;
protected final GenuineVariableDescriptor<Solution_> variableDescriptor; protected final GenuineVariableDescriptor<Solution_> variableDescriptor;
protected final SingletonInverseVariableSupply inverseVariableSupply;
protected final Object toPlanningValue; protected final Object toPlanningValue;


protected final Object oldTrailingLastEntity;
protected final Object newTrailingEntity;

public SubChainReversingChangeMove(SubChain subChain, GenuineVariableDescriptor<Solution_> variableDescriptor, public SubChainReversingChangeMove(SubChain subChain, GenuineVariableDescriptor<Solution_> variableDescriptor,
SingletonInverseVariableSupply inverseVariableSupply, Object toPlanningValue) { SingletonInverseVariableSupply inverseVariableSupply, Object toPlanningValue) {
this.subChain = subChain; this.subChain = subChain;
this.variableDescriptor = variableDescriptor; this.variableDescriptor = variableDescriptor;
this.inverseVariableSupply = inverseVariableSupply;
this.toPlanningValue = toPlanningValue; this.toPlanningValue = toPlanningValue;
oldTrailingLastEntity = inverseVariableSupply.getInverseSingleton(subChain.getLastEntity());
newTrailingEntity = toPlanningValue == null ? null
: inverseVariableSupply.getInverseSingleton(toPlanningValue);
}

public SubChainReversingChangeMove(SubChain subChain, GenuineVariableDescriptor<Solution_> variableDescriptor,
Object toPlanningValue, Object oldTrailingLastEntity, Object newTrailingEntity) {
this.subChain = subChain;
this.variableDescriptor = variableDescriptor;
this.toPlanningValue = toPlanningValue;
this.oldTrailingLastEntity = oldTrailingLastEntity;
this.newTrailingEntity = newTrailingEntity;
} }


public String getVariableName() { public String getVariableName() {
Expand Down Expand Up @@ -75,18 +88,22 @@ public boolean isMoveDoable(ScoreDirector<Solution_> scoreDirector) {
@Override @Override
public SubChainReversingChangeMove<Solution_> createUndoMove(ScoreDirector<Solution_> scoreDirector) { public SubChainReversingChangeMove<Solution_> createUndoMove(ScoreDirector<Solution_> scoreDirector) {
Object oldFirstValue = variableDescriptor.getValue(subChain.getFirstEntity()); Object oldFirstValue = variableDescriptor.getValue(subChain.getFirstEntity());
return new SubChainReversingChangeMove<>(subChain.reverse(), variableDescriptor, inverseVariableSupply, oldFirstValue); boolean unmovedReverse = toPlanningValue == oldFirstValue;
if (!unmovedReverse) {
return new SubChainReversingChangeMove<>(subChain.reverse(), variableDescriptor, oldFirstValue,
newTrailingEntity, oldTrailingLastEntity);
} else {
return new SubChainReversingChangeMove<>(subChain.reverse(), variableDescriptor, oldFirstValue,
oldTrailingLastEntity, newTrailingEntity);
}
} }


@Override @Override
protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector) { protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector) {
Object firstEntity = subChain.getFirstEntity(); Object firstEntity = subChain.getFirstEntity();
Object lastEntity = subChain.getLastEntity(); Object lastEntity = subChain.getLastEntity();
Object oldFirstValue = variableDescriptor.getValue(firstEntity); Object oldFirstValue = variableDescriptor.getValue(firstEntity);
Object oldTrailingLastEntity = inverseVariableSupply.getInverseSingleton(lastEntity); boolean unmovedReverse = toPlanningValue == oldFirstValue;
Object newTrailingEntity = toPlanningValue == null ? null
: inverseVariableSupply.getInverseSingleton(toPlanningValue);
boolean unmovedReverse = newTrailingEntity == firstEntity;
// Close the old chain // Close the old chain
if (!unmovedReverse) { if (!unmovedReverse) {
if (oldTrailingLastEntity != null) { if (oldTrailingLastEntity != null) {
Expand Down Expand Up @@ -122,8 +139,10 @@ private void reverseChain(ScoreDirector<Solution_> scoreDirector, Object entity,
@Override @Override
public SubChainReversingChangeMove<Solution_> rebase(ScoreDirector<Solution_> destinationScoreDirector) { public SubChainReversingChangeMove<Solution_> rebase(ScoreDirector<Solution_> destinationScoreDirector) {
return new SubChainReversingChangeMove<>(subChain.rebase(destinationScoreDirector), return new SubChainReversingChangeMove<>(subChain.rebase(destinationScoreDirector),
variableDescriptor, inverseVariableSupply, variableDescriptor,
destinationScoreDirector.lookUpWorkingObject(toPlanningValue)); destinationScoreDirector.lookUpWorkingObject(toPlanningValue),
destinationScoreDirector.lookUpWorkingObject(oldTrailingLastEntity),
destinationScoreDirector.lookUpWorkingObject(newTrailingEntity));
} }


// ************************************************************************ // ************************************************************************
Expand Down
Expand Up @@ -37,17 +37,30 @@
public class SubChainReversingSwapMove<Solution_> extends AbstractMove<Solution_> { public class SubChainReversingSwapMove<Solution_> extends AbstractMove<Solution_> {


private final GenuineVariableDescriptor<Solution_> variableDescriptor; private final GenuineVariableDescriptor<Solution_> variableDescriptor;
protected final SingletonInverseVariableSupply inverseVariableSupply;


private final SubChain leftSubChain; protected final SubChain leftSubChain;
private final SubChain rightSubChain; protected final Object leftTrailingLastEntity;
protected final SubChain rightSubChain;
protected final Object rightTrailingLastEntity;


public SubChainReversingSwapMove(GenuineVariableDescriptor<Solution_> variableDescriptor, SingletonInverseVariableSupply inverseVariableSupply, public SubChainReversingSwapMove(GenuineVariableDescriptor<Solution_> variableDescriptor,
SingletonInverseVariableSupply inverseVariableSupply,
SubChain leftSubChain, SubChain rightSubChain) { SubChain leftSubChain, SubChain rightSubChain) {
this.variableDescriptor = variableDescriptor; this.variableDescriptor = variableDescriptor;
this.inverseVariableSupply = inverseVariableSupply;
this.leftSubChain = leftSubChain; this.leftSubChain = leftSubChain;
leftTrailingLastEntity = inverseVariableSupply.getInverseSingleton(leftSubChain.getLastEntity());
this.rightSubChain = rightSubChain; this.rightSubChain = rightSubChain;
rightTrailingLastEntity = inverseVariableSupply.getInverseSingleton(rightSubChain.getLastEntity());
}

public SubChainReversingSwapMove(GenuineVariableDescriptor<Solution_> variableDescriptor,
SubChain leftSubChain, Object leftTrailingLastEntity,
SubChain rightSubChain, Object rightTrailingLastEntity) {
this.variableDescriptor = variableDescriptor;
this.leftSubChain = leftSubChain;
this.rightSubChain = rightSubChain;
this.leftTrailingLastEntity = leftTrailingLastEntity;
this.rightTrailingLastEntity = rightTrailingLastEntity;
} }


public SubChain getLeftSubChain() { public SubChain getLeftSubChain() {
Expand Down Expand Up @@ -75,20 +88,19 @@ public boolean isMoveDoable(ScoreDirector<Solution_> scoreDirector) {


@Override @Override
public SubChainReversingSwapMove<Solution_> createUndoMove(ScoreDirector<Solution_> scoreDirector) { public SubChainReversingSwapMove<Solution_> createUndoMove(ScoreDirector<Solution_> scoreDirector) {
return new SubChainReversingSwapMove<>(variableDescriptor, inverseVariableSupply, return new SubChainReversingSwapMove<>(variableDescriptor,
rightSubChain.reverse(), leftSubChain.reverse()); rightSubChain.reverse(), leftTrailingLastEntity,
leftSubChain.reverse(), rightTrailingLastEntity);
} }


@Override @Override
protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector) { protected void doMoveOnGenuineVariables(ScoreDirector<Solution_> scoreDirector) {
Object leftFirstEntity = leftSubChain.getFirstEntity(); Object leftFirstEntity = leftSubChain.getFirstEntity();
Object leftFirstValue = variableDescriptor.getValue(leftFirstEntity); Object leftFirstValue = variableDescriptor.getValue(leftFirstEntity);
Object leftLastEntity = leftSubChain.getLastEntity(); Object leftLastEntity = leftSubChain.getLastEntity();
Object leftTrailingLastEntity = inverseVariableSupply.getInverseSingleton(leftLastEntity);
Object rightFirstEntity = rightSubChain.getFirstEntity(); Object rightFirstEntity = rightSubChain.getFirstEntity();
Object rightFirstValue = variableDescriptor.getValue(rightFirstEntity); Object rightFirstValue = variableDescriptor.getValue(rightFirstEntity);
Object rightLastEntity = rightSubChain.getLastEntity(); Object rightLastEntity = rightSubChain.getLastEntity();
Object rightTrailingLastEntity = inverseVariableSupply.getInverseSingleton(rightLastEntity);
Object leftLastEntityValue = variableDescriptor.getValue(leftLastEntity); Object leftLastEntityValue = variableDescriptor.getValue(leftLastEntity);
Object rightLastEntityValue = variableDescriptor.getValue(rightLastEntity); Object rightLastEntityValue = variableDescriptor.getValue(rightLastEntity);
// Change the entities // Change the entities
Expand Down Expand Up @@ -129,9 +141,11 @@ private void reverseChain(ScoreDirector<Solution_> scoreDirector, Object entity,


@Override @Override
public SubChainReversingSwapMove<Solution_> rebase(ScoreDirector<Solution_> destinationScoreDirector) { public SubChainReversingSwapMove<Solution_> rebase(ScoreDirector<Solution_> destinationScoreDirector) {
return new SubChainReversingSwapMove<>(variableDescriptor, inverseVariableSupply, return new SubChainReversingSwapMove<>(variableDescriptor,
leftSubChain.rebase(destinationScoreDirector), leftSubChain.rebase(destinationScoreDirector),
rightSubChain.rebase(destinationScoreDirector)); destinationScoreDirector.lookUpWorkingObject(leftTrailingLastEntity),
rightSubChain.rebase(destinationScoreDirector),
destinationScoreDirector.lookUpWorkingObject(rightTrailingLastEntity));
} }


// ************************************************************************ // ************************************************************************
Expand Down

0 comments on commit 7667daf

Please sign in to comment.