diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/JoinGraph.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/JoinGraph.java index decb9ee4..26f6bccc 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/JoinGraph.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/JoinGraph.java @@ -23,10 +23,12 @@ package com.kingsrook.qqq.backend.core.actions.metadata; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.TreeSet; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData; @@ -184,6 +186,267 @@ public class JoinGraph + public record JoinConnection(String joinTable, String viaJoinName) implements Comparable + { + + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public int compareTo(JoinConnection that) + { + Comparator comparator = Comparator.comparing((JoinConnection jc) -> jc.joinTable()) + .thenComparing((JoinConnection jc) -> jc.viaJoinName()); + return (comparator.compare(this, that)); + } + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public record JoinConnectionList(List list) implements Comparable + { + + /******************************************************************************* + ** + *******************************************************************************/ + public JoinConnectionList copy() + { + return new JoinConnectionList(new ArrayList<>(list)); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public int compareTo(JoinConnectionList that) + { + if(this.equals(that)) + { + return (0); + } + + for(int i = 0; i < Math.min(this.list.size(), that.list.size()); i++) + { + int comp = this.list.get(i).compareTo(that.list.get(i)); + if(comp != 0) + { + return (comp); + } + } + + return (this.list.size() - that.list.size()); + } + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public Set getJoinConnections(String tableName) + { + Set rs = new TreeSet<>(); + doGetJoinConnections(rs, tableName, new ArrayList<>(), new JoinConnectionList(new ArrayList<>())); + return (rs); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private void doGetJoinConnections(Set joinConnections, String tableName, List path, JoinConnectionList connectionList) + { + for(Edge edge : edges) + { + if(edge.leftTable.equals(tableName) || edge.rightTable.equals(tableName)) + { + if(path.contains(edge.joinName)) + { + continue; + } + + List newPath = new ArrayList<>(path); + newPath.add(edge.joinName); + if(!joinConnectionsContain(joinConnections, newPath)) + { + String otherTableName = null; + if(!edge.leftTable.equals(tableName)) + { + otherTableName = edge.leftTable; + } + else if(!edge.rightTable.equals(tableName)) + { + otherTableName = edge.rightTable; + } + + if(otherTableName != null) + { + + JoinConnectionList newConnectionList = connectionList.copy(); + JoinConnection joinConnection = new JoinConnection(otherTableName, edge.joinName); + newConnectionList.list.add(joinConnection); + joinConnections.add(newConnectionList); + doGetJoinConnections(joinConnections, otherTableName, new ArrayList<>(newPath), newConnectionList); + } + } + } + } + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private boolean joinConnectionsContain(Set joinPaths, List newPath) + { + for(JoinConnectionList joinConnections : joinPaths) + { + List joinConnectionJoins = joinConnections.list.stream().map(jc -> jc.viaJoinName).toList(); + if(joinConnectionJoins.equals(newPath)) + { + return (true); + } + } + return (false); + } + + + + public record JoinPath(String joinTable, List joinNames) + { + + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public Set getJoinPaths(String tableName) + { + Set rs = new HashSet<>(); + doGetJoinPaths(rs, tableName, new ArrayList<>()); + return (rs); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private void doGetJoinPaths(Set joinPaths, String tableName, List path) + { + for(Edge edge : edges) + { + if(edge.leftTable.equals(tableName) || edge.rightTable.equals(tableName)) + { + if(path.contains(edge.joinName)) + { + continue; + } + + List newPath = new ArrayList<>(path); + newPath.add(edge.joinName); + if(!joinPathsContain(joinPaths, newPath)) + { + String otherTableName = null; + if(!edge.leftTable.equals(tableName)) + { + otherTableName = edge.leftTable; + } + else if(!edge.rightTable.equals(tableName)) + { + otherTableName = edge.rightTable; + } + + if(otherTableName != null) + { + joinPaths.add(new JoinPath(otherTableName, newPath)); + doGetJoinPaths(joinPaths, otherTableName, new ArrayList<>(newPath)); + } + } + } + } + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private boolean joinPathsContain(Set joinPaths, List newPath) + { + for(JoinPath joinPath : joinPaths) + { + if(joinPath.joinNames().equals(newPath)) + { + return (true); + } + } + return (false); + } + + /******************************************************************************* + ** + *******************************************************************************/ + /* + public Set> getJoinPaths(String tableName) + { + Set> rs = new HashSet<>(); + doGetJoinPaths(rs, tableName, new ArrayList<>()); + return (rs); + } + */ + + /******************************************************************************* + ** + *******************************************************************************/ + /* + private void doGetJoinPaths(Set> joinPaths, String tableName, List path) + { + for(Edge edge : edges) + { + if(edge.leftTable.equals(tableName) || edge.rightTable.equals(tableName)) + { + if(path.contains(edge.joinName)) + { + continue; + } + + List newPath = new ArrayList<>(path); + newPath.add(edge.joinName); + if(!joinPaths.contains(newPath)) + { + joinPaths.add(newPath); + + String otherTableName = null; + if(!edge.leftTable.equals(tableName)) + { + otherTableName = edge.leftTable; + } + else if(!edge.rightTable.equals(tableName)) + { + otherTableName = edge.rightTable; + } + + if(otherTableName != null) + { + doGetJoinPaths(joinPaths, otherTableName, new ArrayList<>(newPath)); + } + } + } + } + } + */ + + + /******************************************************************************* ** *******************************************************************************/