es.usc.citius.hipster.graph.HashBasedHipsterGraph Maven / Gradle / Ivy
/*
* Copyright 2014 CITIUS , University of Santiago de Compostela.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package es.usc.citius.hipster.graph;
import es.usc.citius.hipster.util.F;
import es.usc.citius.hipster.util.Function;
import java.util.*;
/**
* Lightweight implementation of an in-memory, mutable graph backed to a {@link HashMap} where
* keys are vertices and edges are {@link GraphEdge}s
*/
public class HashBasedHipsterGraph implements HipsterMutableGraph {
protected HashMap>> connected;
public HashBasedHipsterGraph(){
this.connected = new HashMap>>();
}
@Override
public boolean add(V v){
//add a new entry to the hash map if it does not exist
if(!connected.containsKey(v)){
connected.put(v, new LinkedHashSet>());
return true;
}
return false;
}
@Override
public Set add(V... vertices) {
Set added = new HashSet();
for(V v : vertices){
if (add(v)) added.add(v);
}
return added;
}
@Override
public boolean remove(V v){
// Remove all edges related to v
Set> edges = this.connected.get(v);
if (edges == null) return false;
for(Iterator> it = edges.iterator(); it.hasNext(); ){
// Remove the edge in the list of the selected vertex
GraphEdge edge = it.next();
it.remove();
V v2 = edge.getVertex1().equals(v) ? edge.getVertex2() : edge.getVertex1();
for(Iterator> it2 = this.connected.get(v2).iterator(); it2.hasNext();){
GraphEdge edge2 = it2.next();
if (edge2.getVertex1().equals(v) || edge2.getVertex2().equals(v)){
it2.remove();
}
}
}
this.connected.remove(v);
return true;
}
@Override
public Set remove(V... vertices) {
Set removed = new HashSet();
for(V v : vertices){
if (remove(v)) removed.add(v);
}
return removed;
}
@Override
public GraphEdge connect(V v1, V v2, E value){
// Check non-null arguments
if(v1 == null || v2 == null) throw new IllegalArgumentException("Invalid vertices. A vertex cannot be null");
// Ensure that the vertices are in the graph
if (!connected.containsKey(v1)) throw new IllegalArgumentException(v1 + " is not a vertex of the graph");
if (!connected.containsKey(v2)) throw new IllegalArgumentException(v2 + " is not a vertex of the graph");
GraphEdge edge = buildEdge(v1, v2, value);
// Associate the vertices with their edge
connected.get(v1).add(edge);
connected.get(v2).add(edge);
return edge;
}
public GraphEdge buildEdge(V v1, V v2, E value){
return new UndirectedEdge(v1, v2, value);
}
private Map.Entry> createEntry(final V vertex, final GraphEdge edge){
return new Map.Entry>() {
@Override
public V getKey() {
return vertex;
}
@Override
public GraphEdge getValue() {
return edge;
}
@Override
public GraphEdge setValue(GraphEdge value) {
throw new UnsupportedOperationException();
}
};
}
protected Iterable>> vedges(){
// TODO: [java-8-migration]
return F.flatMap(connected.entrySet(), new Function>>, Iterable>>>() {
@Override
public Iterable>> apply(final Map.Entry>> entry) {
return F.map(entry.getValue(), new Function, Map.Entry>>() {
@Override
public Map.Entry> apply(GraphEdge input) {
return createEntry(entry.getKey(), input);
}
});
}
});
}
/**
* Returns a list of the edges in the graph.
* @return edges of the graph.
*/
@Override
public Iterable> edges() {
return F.map(vedges(), new Function>, GraphEdge>() {
@Override
public GraphEdge apply(Map.Entry> entry) {
return entry.getValue();
}
});
}
/**
* Returns the vertices of the graph. Any changes in the
* returned iterator affect the underlying graph structure.
* @return iterator with the vertices of the graph
*/
@Override
public Iterable vertices() {
return connected.keySet();
}
@Override
public Iterable> edgesOf(V vertex) {
Set> set = connected.get(vertex);
if (set == null) set = Collections.emptySet();
return set;
}
/**
* Returns the internal HashMap representation of the graph
* @return HashMap where keys are vertices and values a set with the connected edges
*/
public HashMap>> getConnected() {
return connected;
}
public void setConnected(HashMap>> connected) {
this.connected = connected;
}
public static HashBasedHipsterGraph create() {
return new HashBasedHipsterGraph();
}
}