/*******************************************************************************
* Copyright 2010 Universidade do Minho, Ricardo Vila�a and Francisco Cruz
*
* 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 org.ublog.graph;
import java.io.FileWriter;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import org.jgrapht.DirectedGraph;
import org.jgrapht.Graph;
import org.jgrapht.UndirectedGraph;
import org.jgrapht.VertexFactory;
import org.jgrapht.ext.DOTExporter;
import org.jgrapht.generate.ScaleFreeGraphGenerator;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.SimpleGraph;
import org.ublog.benchmark.social.User;
public class GraphImpl implements GraphInterface,VertexFactory<User>{
private static final long serialVersionUID = 1L;
private static Map<Integer,User> mapUser;
private static DirectedGraph<User,DefaultEdge> graph;
private static UndirectedGraph<String,DefaultEdge> grausTags;
private int somaGraus;
private int tagID;
private int size;
private static int userID;
private static boolean hasInitiated;
public GraphImpl() throws RemoteException {
hasInitiated = false;
}
public synchronized boolean init(int size) throws RemoteException {
if(hasInitiated == false ){
this.size = size;
userID=0;
mapUser=new HashMap<Integer, User>();
ScaleFreeGraphGenerator<User,DefaultEdge> gen = new ScaleFreeGraphGenerator<User,DefaultEdge>(size,123456789);
graph=new DefaultDirectedGraph<User, DefaultEdge>(DefaultEdge.class);
gen.generateGraph(graph,this,null);
this.exportToDot("graph-init.dot");
this.tagID=0;
ScaleFreeGraphGenerator<String,DefaultEdge> gen2 = new ScaleFreeGraphGenerator<String,DefaultEdge>(64,987654321);
grausTags=new SimpleGraph<String, DefaultEdge>(DefaultEdge.class);
gen2.generateGraph(grausTags,new VertexFactory<String>(){
@Override
public String createVertex() {
String res="topico"+tagID;
tagID++;
return res;
}
},null);
for(String vertex:grausTags.vertexSet())
{
this.somaGraus+=grausTags.degreeOf(vertex);
}
this.exportToDotGraus("graus.dot",grausTags);
hasInitiated = true;
return false;
}
else {
System.out.println("The graph was already initiated");
return hasInitiated;
}
}
public User createVertex()
{
User res=new User();
res.setName("User "+userID);
res.setUsername("user"+userID);
res.setCreated(new Date());
res.setPassword("123456");
mapUser.put(userID,res);
userID++;
return res;
}
public void exportToDot(String fileName)
{
try {
new DOTExporter<User,DefaultEdge>().export(new FileWriter(fileName), graph);
} catch (IOException e) {
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public void exportToDotGraus(String fileName, Graph graph)
{
try {
new DOTExporter<String,DefaultEdge>().export(new FileWriter(fileName), grausTags);
} catch (IOException e) {
e.printStackTrace();
}
}
public int getRandomFriend(User myUser) throws RemoteException{
List<User> friends=new ArrayList<User>();
for(DefaultEdge edge:graph.outgoingEdgesOf(myUser))
{
if (graph.containsEdge(graph.getEdgeTarget(edge),myUser))
{
friends.add(graph.getEdgeTarget(edge));
}
}
if (friends.isEmpty())
{
return -1;
}
else
{
Random rnd=new Random();
int pos=rnd.nextInt(friends.size());
int userID=new Integer(friends.get(pos).getUsername().substring(4));
return userID;
}
}
@Override
public synchronized String getNextStopFollowingUser(User user) throws RemoteException {
// Da o utilizador com menos seguidores ao qual o user ainda segue
int min=Integer.MAX_VALUE;
User res=null;
for(User tmp:graph.vertexSet())
{
if (!user.equals(tmp) && graph.containsEdge(user, tmp) && graph.incomingEdgesOf(tmp).size()<min)
{
min=graph.incomingEdgesOf(tmp).size();
res=tmp;
}
}
if (res!=null)
{
graph.removeEdge(user, res);
return res.getUsername();
}
else return null;
}
@Override
public int degreeOfGrausTags(String str) throws RemoteException {
return grausTags.degreeOf(str);
}
@Override
public User getClientCount(int clientCount) throws RemoteException {
return mapUser.get(clientCount);
}
@Override
public Set<String> getFollowers(User currentUser) throws RemoteException {
Set<String> followers=new HashSet<String>();
for (DefaultEdge edge:graph.incomingEdgesOf(currentUser))
{
followers.add(graph.getEdgeSource(edge).getUsername());
}
return followers;
}
@Override
public Set<String> getFollowing(User currentUser) throws RemoteException {
Set<String> following=new HashSet<String>();
for (DefaultEdge edge:graph.outgoingEdgesOf(currentUser))
{
following.add(graph.getEdgeTarget(edge).getUsername());
}
return following;
}
@Override
public User getMapUser(int i) throws RemoteException {
return mapUser.get(i);
}
@Override
public int getSomaGraus() throws RemoteException {
return this.somaGraus;
}
@Override
public boolean graphContainsEdge(User user, int userID)
throws RemoteException {
return graph.containsEdge(user, mapUser.get(userID));
}
@Override
public int getUserID() throws RemoteException {
return userID;
}
@Override
public int getOutDegreeOf(int currentUser) throws RemoteException {
return graph.outDegreeOf(mapUser.get(currentUser));
}
}