Added project

This commit is contained in:
2023-06-11 00:14:30 +03:00
parent a9048a9b39
commit 32c1d5fb0b
103 changed files with 9633 additions and 2 deletions

View File

@@ -0,0 +1,215 @@
package ru.resprojects.linkchecker.services;
import org.jgrapht.Graph;
import org.jgrapht.alg.interfaces.ShortestPathAlgorithm;
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
import org.jgrapht.graph.DefaultEdge;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import ru.resprojects.linkchecker.AppProperties;
import ru.resprojects.linkchecker.dto.GraphDto;
import ru.resprojects.linkchecker.model.AbstractNamedEntity;
import ru.resprojects.linkchecker.model.Edge;
import ru.resprojects.linkchecker.model.Node;
import ru.resprojects.linkchecker.util.GraphUtil;
import ru.resprojects.linkchecker.util.exeptions.ApplicationException;
import ru.resprojects.linkchecker.util.exeptions.ErrorPlaceType;
import ru.resprojects.linkchecker.util.exeptions.ErrorType;
import ru.resprojects.linkchecker.util.exeptions.NotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static ru.resprojects.linkchecker.dto.GraphDto.NodeGraph;
import static ru.resprojects.linkchecker.dto.GraphDto.EdgeGraph;
import static ru.resprojects.linkchecker.util.GraphUtil.*;
@Service
public class GraphServiceImpl implements GraphService {
private final GraphEdgeService edges;
private final GraphNodeService nodes;
private final AppProperties properties;
@Autowired
public GraphServiceImpl(final GraphEdgeService edges, final GraphNodeService nodes, final AppProperties properties) {
this.edges = edges;
this.nodes = nodes;
this.properties = properties;
}
@Override
public GraphDto create(final GraphDto graphTo) throws ApplicationException {
if (Objects.isNull(graphTo)) {
throw new ApplicationException(
ErrorType.DATA_ERROR,
ErrorPlaceType.GRAPH,
HttpStatus.UNPROCESSABLE_ENTITY,
properties.getAppMsg().get("MSG_ARGUMENT_NULL")
);
}
if (graphTo.getNodes().isEmpty() && !graphTo.getEdges().isEmpty()) {
throw new ApplicationException(
ErrorType.DATA_ERROR,
ErrorPlaceType.GRAPH,
HttpStatus.UNPROCESSABLE_ENTITY,
"NODES: " + properties.getAppMsg().get("MSG_COLLECTION_EMPTY")
);
}
clear();
GraphDto graph = graphToGraphDto(
removeCyclesFromGraph(graphBuilder(graphTo.getNodes(), graphTo.getEdges())));
Set<NodeGraph> nodeGraphSet = nodes.create(graph.getNodes());
Set<EdgeGraph> edgeGraphSet = edges.create(graph.getEdges());
return new GraphDto(nodeGraphSet, edgeGraphSet);
}
@Override
public GraphDto get() {
return removeGraphCycles(new GraphDto(nodes.getAll(), edges.getAll()));
}
@Override
public String exportToGraphViz() {
return GraphUtil.exportToGraphViz(get());
}
@Override
public void clear() {
nodes.deleteAll();
}
@Override
public String checkRoute(final Set<String> nodeNameSet) throws NotFoundException {
if (Objects.isNull(nodeNameSet)) {
throw new ApplicationException(
ErrorType.DATA_ERROR,
ErrorPlaceType.GRAPH,
HttpStatus.UNPROCESSABLE_ENTITY,
properties.getAppMsg().get("MSG_ARGUMENT_NULL")
);
}
if (nodeNameSet.isEmpty()) {
throw new ApplicationException(
ErrorType.DATA_ERROR,
ErrorPlaceType.GRAPH,
HttpStatus.UNPROCESSABLE_ENTITY,
properties.getAppMsg().get("MSG_COLLECTION_EMPTY")
);
}
if (nodeNameSet.size() == 1) {
throw new ApplicationException(
ErrorType.DATA_ERROR,
ErrorPlaceType.GRAPH,
HttpStatus.UNPROCESSABLE_ENTITY,
properties.getAppMsg().get("MSG_COLLECTION_CONTAIN_ONE_ELEMENT")
);
}
GraphDto graphDto = removeGraphCycles(new GraphDto(nodes.getAll(),
edges.getAll()));
Map<String, Boolean> faultNodes = getRandomNodeFault(graphDto.getNodes());
List<String> nodeNameList = new ArrayList<>(nodeNameSet);
Graph<Node, DefaultEdge> graph = graphBuilder(graphDto.getNodes(),
graphDto.getEdges());
DijkstraShortestPath<Node, DefaultEdge> dAlg = new DijkstraShortestPath<>(graph);
Node firstNode = nodeGraphToNode(graphDto.getNodes().stream()
.filter(ng -> ng.getName().equalsIgnoreCase(nodeNameList.get(0)))
.findFirst()
.orElse(null));
if (Objects.isNull(firstNode)) {
throw new NotFoundException(
String.format(properties.getNodeMsg().get("NODE_MSG_BY_NAME_ERROR"), nodeNameList.get(0)),
ErrorPlaceType.GRAPH
);
}
ShortestPathAlgorithm.SingleSourcePaths<Node, DefaultEdge> paths = dAlg.getPaths(firstNode);
if (faultNodes.getOrDefault(firstNode.getName(), false)) {
throw new NotFoundException(
String.format(properties.getNodeMsg().get("NODE_MSG_IS_FAULT"), firstNode.getName()),
ErrorPlaceType.GRAPH
);
}
nodeNameList.stream().skip(1).forEach(name -> {
Node nextNode = nodeGraphToNode(graphDto.getNodes().stream()
.filter(ng -> ng.getName().equalsIgnoreCase(name))
.findFirst()
.orElse(null));
if (Objects.isNull(nextNode)) {
throw new NotFoundException(
String.format(properties.getNodeMsg().get("NODE_MSG_BY_NAME_ERROR"), name),
ErrorPlaceType.GRAPH
);
}
if (faultNodes.getOrDefault(nextNode.getName(), false)) {
throw new NotFoundException(
String.format(properties.getNodeMsg().get("NODE_MSG_IS_FAULT"), name),
ErrorPlaceType.GRAPH
);
}
List<Node> findNodes = paths.getPath(nextNode).getVertexList();
List<String> findNodesName = findNodes.stream()
.map(AbstractNamedEntity::getName)
.collect(Collectors.toList());
if (!nodeNameList.containsAll(findNodesName)) {
throw new NotFoundException(
String.format(properties.getNodeMsg().get("NODE_MSG_NOT_REACHABLE"), nodeNameList.get(0), name),
ErrorPlaceType.GRAPH
);
}
});
nodeNameList.forEach(name ->
graphDto.getNodes().stream()
.filter(ng -> ng.getName().equalsIgnoreCase(name))
.findFirst()
.ifPresent(ng -> {
ng.setCounter(ng.getCounter() + 1);
nodes.update(ng);
}));
return String.format("Route for nodes %s is found", nodeNameList.toString());
}
private GraphDto removeGraphCycles(final GraphDto graph) {
if (Objects.isNull(graph) || graph.getEdges().isEmpty()) {
return graph;
}
GraphDto optimizedGraph = graphToGraphDto(
removeCyclesFromGraph(graphBuilder(graph.getNodes(), graph.getEdges())));
//Checking, was removed edges or not from graph after optimizing
if (graph.getEdges().size() == optimizedGraph.getEdges().size()) {
return graph;
}
//Because ID's lost's in optimized graph, we need recover them.
Set<EdgeGraph> optimizedEdges = graph.getEdges().stream()
.filter(e -> optimizedGraph.getEdges().stream()
.anyMatch(eg -> eg.getNodeOne().equalsIgnoreCase(e.getNodeOne())
&& eg.getNodeTwo().equalsIgnoreCase(e.getNodeTwo())))
.collect(Collectors.toSet());
//Rewrite edge collection in optimized graph.
optimizedGraph.setEdges(optimizedEdges);
//Search all edges that was removed from graph and remove them from DB.
Set<EdgeGraph> removedEdgesGraph = graph.getEdges().stream()
.filter(eg -> !optimizedGraph.getEdges().contains(eg))
.collect(Collectors.toSet());
Set<Edge> removedEdges = getEdgesFromGraphDto(new GraphDto(
optimizedGraph.getNodes(),
removedEdgesGraph));
if (!removedEdges.isEmpty()) {
edges.delete(removedEdges);
return optimizedGraph;
}
return graph;
}
public GraphEdgeService getEdges() {
return edges;
}
public GraphNodeService getNodes() {
return nodes;
}
}