package i5.las2peer.services.ocd.algorithms;
import i5.las2peer.services.ocd.adapters.coverInput.CommunityMemberListsCoverInputAdapter;
import i5.las2peer.services.ocd.adapters.coverInput.CoverInputAdapterFactory;
import i5.las2peer.services.ocd.adapters.coverInput.CoverInputFormat;
import i5.las2peer.services.ocd.adapters.graphOutput.DocaGraphOutputAdapter;
import i5.las2peer.services.ocd.adapters.graphOutput.GraphOutputAdapter;
import i5.las2peer.services.ocd.algorithms.utils.OcdAlgorithmException;
import i5.las2peer.services.ocd.benchmarks.OcdBenchmarkException;
import i5.las2peer.services.ocd.graphs.Cover;
import i5.las2peer.services.ocd.graphs.CoverCreationType;
import i5.las2peer.services.ocd.graphs.CustomGraph;
import i5.las2peer.services.ocd.graphs.GraphType;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecuteResultHandler;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.lang3.SystemUtils;
public class DetectingOverlappingCommunitiesAlgorithm implements OcdAlgorithm {
/*
* Path of the directory reserved for the doca application.
*/
private static final String docaDirectoryPath = "ocd/doca/";
/*
* Used for synchronization purposes. Executes the algorithm.
*/
private static DefaultExecutor executor = new DefaultExecutor();
/* Path of the file holding an application that executes the DOCA algorithm. For Windows.
*/
private static String windowsAlgorithmPath = docaDirectoryPath + "DocaWindows.exe";
/* Path of the file holding an application that executes the DOCA algorithm. For Linux.
*/
private static String linuxAlgorithmPath = "./DocaLinux";
/*
* Filename parameter passed to the Doca Application.
*/
private static final String docaGraphPath = "network.txt";
/*
* Path of the file containing the input graph.
*/
private static final String graphPath = docaDirectoryPath + docaGraphPath;
/*
* Path of the file containing the output cover.
*/
private static final String coverPath = docaDirectoryPath + "cover.txt";
/**
* The overlapping threshold.
* The default value is 0.75. Must be higher than 0 and lower than 2.
*/
private double overlappingThreshold = 0.75;
/*
* PARAMETER NAMES
*/
private static String OVERLAPPING_THRESHOLD_NAME = "overlappingThreshold";
@Override
public void setParameters(Map<String, String> parameters) {
if(parameters.containsKey(OVERLAPPING_THRESHOLD_NAME)) {
overlappingThreshold = Double.parseDouble(parameters.get(OVERLAPPING_THRESHOLD_NAME));
if(overlappingThreshold <= 0 || overlappingThreshold >= 2) {
throw new IllegalArgumentException();
}
parameters.remove(OVERLAPPING_THRESHOLD_NAME);
}
if(parameters.size() > 0) {
throw new IllegalArgumentException();
}
}
@Override
public Map<String, String> getParameters() {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(OVERLAPPING_THRESHOLD_NAME, Double.toString(overlappingThreshold));
return parameters;
}
@Override
public CoverCreationType getAlgorithmType() {
/*
* TODO reinsert for use on Windows / when implemented for Linux
*/
// return CoverCreationType.DETECTING_OVERLAPPING_COMMUNITIES_ALGORITHM;
return null;
}
@Override
public Set<GraphType> compatibleGraphTypes() {
Set<GraphType> compatibilities = new HashSet<GraphType>();
return compatibilities;
}
@Override
public Cover detectOverlappingCommunities(CustomGraph graph)
throws OcdAlgorithmException, InterruptedException {
synchronized (executor) {
try {
CustomGraph graphCpy = new CustomGraph(graph);
GraphOutputAdapter graphAdapter = new DocaGraphOutputAdapter();
graphAdapter.setWriter(new FileWriter(graphPath));
graphAdapter.writeGraph(graphCpy);
String executorFilename;
if(SystemUtils.IS_OS_WINDOWS) {
executorFilename = windowsAlgorithmPath;
}
// TODO generate for linux
/*
else if(SystemUtils.IS_OS_LINUX) {
executorFilename = linuxAlgorithmPath;
}*/
/*
* Algorithm not implemented for this operating system.
*/
else {
throw new OcdBenchmarkException();
}
CommandLine cmdLine = new CommandLine(executorFilename);
cmdLine.addArgument(docaGraphPath);
cmdLine.addArgument(Double.toString(overlappingThreshold));
File workingDirectory = new File(docaDirectoryPath);
executor.setWorkingDirectory(workingDirectory);
DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
executor.execute(cmdLine, resultHandler);
resultHandler.waitFor();
// DOCA defines 1 as OK
if(resultHandler.getExitValue() != 1) {
System.out.println(resultHandler.getException());
throw new OcdAlgorithmException("Doca Process exit value: " + resultHandler.getExitValue());
}
CoverInputAdapterFactory factory = new CoverInputAdapterFactory();
CommunityMemberListsCoverInputAdapter coverAdapter = (CommunityMemberListsCoverInputAdapter)factory.getInstance(CoverInputFormat.COMMUNITY_MEMBERS_LISTS);
coverAdapter.setCommunityNamesDefined(false);
coverAdapter.setReader(new FileReader(coverPath));
Cover coverCpy = coverAdapter.readCover(graphCpy);
Cover cover = new Cover(graph, coverCpy.getMemberships());
return cover;
}
catch(InterruptedException e) {
throw e;
}
catch (Exception e) {
e.printStackTrace();
if(Thread.interrupted()) {
throw new InterruptedException();
}
throw new OcdAlgorithmException(e);
}
}
}
}