code: public SymmetricGraph<Table,Edge<Table>,SQLException> getForeignKeyGraph(final Set<String> tableTypes) {
  		return new SymmetricGraph<Table, Edge<Table>, SQLException>() {
  
  			@Override
  			public Set<Table> getVertices() throws SQLException {
  				Set<Table> vertices = new LinkedHashSet<>();
  				for(Schema schema : getSchemas().values()) {
  					for(Table table : schema.getTables().values()) {
  						if(tableTypes==null || tableTypes.contains(table.getTableType())) vertices.add(table);
  					}
  				}
  				return AoCollections.optimalUnmodifiableSet(vertices);
  			}
  
  			@Override
  			public Set<Edge<Table>> getEdgesFrom(Table from) throws SQLException {
  				Set<? extends Table> tos = from.getImportedTables();
  				Set<Edge<Table>> edges = new LinkedHashSet<>(tos.size()*4/3+1);
  				for(Table to : tos) {
  					if(
  						tableTypes==null
  						|| tableTypes.contains(from.getTableType())
  						|| tableTypes.contains(to.getTableType())
  					) edges.add(new Edge<>(from, to));
  				}
  				return AoCollections.optimalUnmodifiableSet(edges);
  			}
  
  			@Override
  			public Set<Edge<Table>> getEdgesTo(Table to) throws SQLException {
  				Set<? extends Table> froms = to.getExportedTables();
  				Set<Edge<Table>> edges = new LinkedHashSet<>(froms.size()*4/3+1);
  				for(Table from : froms) {
  					if(
  						tableTypes==null
  						|| tableTypes.contains(from.getTableType())
  						|| tableTypes.contains(to.getTableType())
  					) edges.add(new Edge<>(from, to));
  				}
  				return AoCollections.optimalUnmodifiableSet(edges);
  			}
  		};
  	}
docs: Gets a graph view of the imported/exported table relationships within this catalog.
  
  TODO: Check is symmetric in JUnit test
  
  @param the set of tables types or <code>null</code> for all types