matrix routing:
- only allow <2 countries to be passed. - do not route over chains with first node is port or station - check that intermediate nodes have all "intermediate"-proeprty (exception near by routing nodes)
This commit is contained in:
parent
931f5d6713
commit
3a9691dc6f
3 changed files with 63 additions and 8 deletions
|
|
@ -128,6 +128,8 @@ public class ContainerRateRepository {
|
|||
LEFT JOIN node AS from_node ON from_node.id = container_rate.from_node_id
|
||||
LEFT JOIN validity_period ON validity_period.id = container_rate.validity_period_id
|
||||
WHERE validity_period.state = ?
|
||||
AND to_node.is_deprecated = FALSE
|
||||
AND from_node.is_deprecated = FALSE
|
||||
AND (container_rate.container_rate_type = ? OR container_rate.container_rate_type = ?)
|
||||
AND container_rate.from_node_id = ? AND to_node.country_id IN (%s)""".formatted(
|
||||
destinationCountryPlaceholders);
|
||||
|
|
@ -162,6 +164,8 @@ public class ContainerRateRepository {
|
|||
LEFT JOIN node AS from_node ON from_node.id = container_rate.from_node_id
|
||||
LEFT JOIN validity_period ON validity_period.id = container_rate.validity_period_id
|
||||
WHERE validity_period.state = ?
|
||||
AND to_node.is_deprecated = FALSE
|
||||
AND from_node.is_deprecated = FALSE
|
||||
AND container_rate.from_node_id = ? AND container_rate.container_rate_type = ?""";
|
||||
|
||||
return jdbcTemplate.query(query, new ContainerRateMapper(true), ValidityPeriodState.VALID.name(), mainRun.getToNodeId(), TransportType.POST_RUN.name());
|
||||
|
|
@ -206,6 +210,20 @@ public class ContainerRateRepository {
|
|||
);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public boolean hasMainRun(Integer nodeId) {
|
||||
String query = """
|
||||
SELECT EXISTS(
|
||||
SELECT 1 FROM container_rate
|
||||
WHERE (from_node_id = ? OR to_node_id = ?)
|
||||
AND (container_rate_type = ? OR container_rate_type = ?)
|
||||
)
|
||||
""";
|
||||
|
||||
return Boolean.TRUE.equals(jdbcTemplate.queryForObject(query, Boolean.class,
|
||||
nodeId, nodeId, TransportType.SEA.name(), TransportType.RAIL.name()));
|
||||
}
|
||||
|
||||
|
||||
private static class ContainerRateMapper implements RowMapper<ContainerRate> {
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ public class ChainResolver {
|
|||
validationObject.next();
|
||||
}
|
||||
|
||||
if (validationObject.valid())
|
||||
if (validationObject.valid() && !checkDeprecated(validationObject.getChain()))
|
||||
foundChains.add(new ArrayList<>(validationObject.getChain()));
|
||||
} else {
|
||||
log.warn("Circular reference detected while building predecessor chain for node {}", nodeId);
|
||||
|
|
@ -80,11 +80,19 @@ public class ChainResolver {
|
|||
|
||||
}
|
||||
|
||||
// remove chains if there is a node that cannot act as intermediate.
|
||||
foundChains = foundChains.stream().filter(chain -> chain.stream().anyMatch(n -> !n.getIntermediate())).toList();
|
||||
|
||||
|
||||
log.info("Found {} chains for node {}", foundChains.size(), nodeId);
|
||||
log.info("Found chains: {}", foundChains);
|
||||
return foundChains;
|
||||
}
|
||||
|
||||
private boolean checkDeprecated(List<Node> chain) {
|
||||
return chain.stream().anyMatch(Node::getDeprecated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class for chain validation and processing.
|
||||
* <p>
|
||||
|
|
@ -96,13 +104,19 @@ public class ChainResolver {
|
|||
@Renderer(text = "getFullChainView()")
|
||||
private static class ChainValidationObject {
|
||||
|
||||
/** Current position in the chain being processed */
|
||||
/**
|
||||
* Current position in the chain being processed
|
||||
*/
|
||||
int chainPointer;
|
||||
|
||||
/** List of nodes representing the current chain */
|
||||
/**
|
||||
* List of nodes representing the current chain
|
||||
*/
|
||||
List<Node> chain;
|
||||
|
||||
/** Flag indicating if the chain is valid */
|
||||
/**
|
||||
* Flag indicating if the chain is valid
|
||||
*/
|
||||
private boolean chainValid;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -309,6 +309,10 @@ public class RoutingService {
|
|||
Collection<TemporaryRateObject> rates = container.getRates();
|
||||
|
||||
for (var chain : chains) {
|
||||
|
||||
if (skipCain(chain, container))
|
||||
continue;
|
||||
|
||||
var toNode = chain.isEmpty() ? container.getDestinationNode() : chain.getLast();
|
||||
|
||||
TemporaryRateObject finalSection = new TemporaryRateObject(container.getSourceNode(), toNode, TemporaryRateObject.TemporaryRateObjectType.MATRIX);
|
||||
|
|
@ -363,9 +367,21 @@ public class RoutingService {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean skipCain(List<Node> chain, TemporaryContainer container) {
|
||||
if (containerRateRepository.hasMainRun(chain.getFirst().getId()))
|
||||
return true;
|
||||
|
||||
Set<Integer> countryIds = new HashSet<>();
|
||||
countryIds.add(container.getSourceNode().getCountryId());
|
||||
chain.forEach(node -> countryIds.add(node.getCountryId()));
|
||||
return countryIds.size() > 2;
|
||||
}
|
||||
|
||||
|
||||
private TemporaryRateObject connectNearByNodes(Node chainEnd, List<Node> nearByNodes, TemporaryContainer container) {
|
||||
|
||||
if(nearByNodes == null)
|
||||
return null;
|
||||
|
||||
for (var nearbyNode : nearByNodes) {
|
||||
TemporaryRateObject nearByRate = connectNodes(nearbyNode, chainEnd, container);
|
||||
|
|
@ -541,6 +557,9 @@ public class RoutingService {
|
|||
Node mainRunEndNode = nodeRepository.getById(mainRun.getToNodeId()).orElseThrow();
|
||||
Node mainRunStartNode = outboundNodes.stream().filter(n -> n.getId().equals(mainRun.getFromNodeId())).findFirst().orElseThrow();
|
||||
|
||||
if(!mainRunStartNode.getIntermediate() || !mainRunEndNode.getIntermediate())
|
||||
continue;
|
||||
|
||||
TemporaryRateObject mainRunObj = new TemporaryRateObject(mainRunStartNode, mainRunEndNode, TemporaryRateObject.TemporaryRateObjectType.MAIN_RUN, mainRun);
|
||||
|
||||
var postRuns = container.getPostRuns().get(mainRun.getId());
|
||||
|
|
@ -556,6 +575,10 @@ public class RoutingService {
|
|||
for (var postRun : container.getPostRuns().get(mainRun.getId())) {
|
||||
|
||||
Node postRunEndNode = nodeRepository.getById(postRun.getToNodeId()).orElseThrow();
|
||||
|
||||
if (!postRunEndNode.getIntermediate())
|
||||
continue;
|
||||
|
||||
TemporaryRateObject postRunObj = new TemporaryRateObject(mainRunEndNode, postRunEndNode, TemporaryRateObject.TemporaryRateObjectType.POST_RUN, postRun);
|
||||
|
||||
var sortedChains = sortedChainMap.get(quality).get(postRun.getId());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue