<commit_before>package i5.las2peer.services.ocd.adapters.graphInput;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import i5.las2peer.services.ocd.adapters.AdapterException;
import i5.las2peer.services.ocd.graphs.CustomGraph;
import y.base.Edge;
import y.base.Node;

import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.query.ResultSetFormatter;
import org.apache.jena.riot.system.ErrorHandlerFactory;
import org.apache.jena.sparql.core.DatasetImpl;
import org.apache.jena.sparql.engine.http.QueryEngineHTTP;

/**
 * A graph input adapter for importing graphs of relations between LMS users from the tech4comp LMS Triplestore. This will NOT import from a file.
 *
 */
public class LmsTripleStoreGraphInputAdapter extends AbstractGraphInputAdapter {
	
	/////////////////
	//// Variables////
	/////////////////
	/**
	* Boolean for showing usernames or URIs as node names
	*/
	private Boolean showUserNames = false;
	
	/**
	* Comma separated string of URIs of users to be in the graph. If empty, all users will be
	*/
	private String involvedUserURIs = "";
	private ArrayList<String> involvedUsers = new ArrayList<String>();
	
	/**
	 * Starting date of posts to be considered
	 */
	private Date startDate = null;
	
	/**
	 * Ending date of posts to be considered
	 */
	private Date endDate = null;
	
	@Override
	public void setParameter(Map<String, String> param) throws IllegalArgumentException, ParseException {
		if (param.containsKey("showUserNames")) {
			showUserNames = Boolean.parseBoolean(param.get("showUserNames"));
			param.remove("showUserNames");
		}
		if (param.containsKey("involvedUserURIs")) {
			involvedUserURIs = param.get("involvedUserURIs");
			involvedUsers = new ArrayList<String>();

			String[] userUriArray = involvedUserURIs.split(",");
			for (String str : userUriArray) {
				involvedUsers.add(str);
			}
			param.remove("involvedUserURIs");
		}
		SimpleDateFormat df = new SimpleDateFormat ("yyyy-MM-dd");		
		if(param.containsKey("startDate")){
			startDate = df.parse(param.get("startDate"));
			param.remove("startDate");
		}
		if(param.containsKey("endDate")){
			endDate = df.parse(param.get("endDate"));
			param.remove("endDate");
		}
		if(!param.isEmpty()) {
			throw new IllegalArgumentException();
		}
	}
	
	@Override
	public CustomGraph readGraph() throws AdapterException {
		CustomGraph graph = new CustomGraph();
		Map<String, Node> nodeIds = new HashMap<String, Node>();
		
		HashMap<String, String> users = getUsers();
		if(!involvedUsers.isEmpty()) {
			for(String userUri : involvedUsers) {
				if(users.containsKey(userUri)) {
					Node userNode = graph.createNode(); 
					if(showUserNames) {
						graph.setNodeName(userNode, users.get(userUri));
					}
					else {
						graph.setNodeName(userNode, userUri);
					}
					
					nodeIds.put(userUri, userNode);
				}
			}
		}
		else {
			//create nodes for all users
			for(Map.Entry<String, String> user : users.entrySet()) {
				Node userNode = graph.createNode(); 
				if(showUserNames) {
					graph.setNodeName(userNode, user.getValue());
				}
				else {
					graph.setNodeName(userNode, user.getKey());
				}
				
				nodeIds.put(user.getKey(), userNode);
			}
		}
		
		//Iterate through each user, get their created resources. Then get the other users that interacted with those and draw edges from them to the user
		for(Map.Entry<String, Node> user : nodeIds.entrySet()) { 
			ArrayList<String> resources = getCreatedResources(user.getKey());
			ArrayList<String> interactingUsers = getInteractingUsers(resources);
			
			for(String interactingUser : interactingUsers) {
				//System.out.println("USERS: " + user.getKey() + " " + interactingUser);
				if(nodeIds.containsKey(interactingUser)) {
					graph.createEdge(nodeIds.get(interactingUser), user.getValue());
				}
			}
		}
		
		return graph;
	}
	
	/**
	 * Queries all usernames from the LMS Triplestore
	 * @return A HashMap of all profiles with their urls as keys and their names as values
	 */
	private HashMap<String, String> getUsers() {
				
		String usersQueryString = 
			    "PREFIX w3: <http://www.w3.org/2000/01/rdf-schema#> " +
			    "PREFIX leip: <http://uni-leipzig.de/tech4comp/ontology/> " +
			    "SELECT DISTINCT ?profile ?user " +
			    "WHERE { " +
			    " GRAPH <https://triplestore.tech4comp.dbis.rwth-aachen.de/LMSData/data> { " +
			    "      ?profile a leip:user . " +
			    "      ?profile w3:label ?user . " +
			    "      } " +
			    "	}";
		<commit_msg>Add error handling for LMS Triplestore input handler<commit_after>package i5.las2peer.services.ocd.adapters.graphInput;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import i5.las2peer.services.ocd.adapters.AdapterException;
import i5.las2peer.services.ocd.graphs.CustomGraph;
import y.base.Edge;
import y.base.Node;

import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.query.ResultSetFormatter;
import org.apache.jena.riot.system.ErrorHandlerFactory;
import org.apache.jena.sparql.core.DatasetImpl;
import org.apache.jena.sparql.engine.http.QueryEngineHTTP;

/**
 * A graph input adapter for importing graphs of relations between LMS users from the tech4comp LMS Triplestore. This will NOT import from a file.
 *
 */
public class LmsTripleStoreGraphInputAdapter extends AbstractGraphInputAdapter {
	
	/////////////////
	//// Variables////
	/////////////////
	/**
	* Boolean for showing usernames or URIs as node names
	*/
	private Boolean showUserNames = false;
	
	/**
	* Comma separated string of URIs of users to be in the graph. If empty, all users will be
	*/
	private String involvedUserURIs = "";
	private ArrayList<String> involvedUsers = new ArrayList<String>();
	
	/**
	 * Starting date of posts to be considered
	 */
	private Date startDate = null;
	
	/**
	 * Ending date of posts to be considered
	 */
	private Date endDate = null;
	
	@Override
	public void setParameter(Map<String, String> param) throws IllegalArgumentException, ParseException {
		if (param.containsKey("showUserNames")) {
			showUserNames = Boolean.parseBoolean(param.get("showUserNames"));
			param.remove("showUserNames");
		}
		if (param.containsKey("involvedUserURIs")) {
			involvedUserURIs = param.get("involvedUserURIs");
			involvedUsers = new ArrayList<String>();

			String[] userUriArray = involvedUserURIs.split(",");
			for (String str : userUriArray) {
				involvedUsers.add(str);
			}
			param.remove("involvedUserURIs");
		}
		SimpleDateFormat df = new SimpleDateFormat ("yyyy-MM-dd");		
		if(param.containsKey("startDate")){
			startDate = df.parse(param.get("startDate"));
			param.remove("startDate");
		}
		if(param.containsKey("endDate")){
			endDate = df.parse(param.get("endDate"));
			param.remove("endDate");
		}
		if(!param.isEmpty()) {
			throw new IllegalArgumentException();
		}
	}
	
	@Override
	public CustomGraph readGraph() throws AdapterException {
		CustomGraph graph = new CustomGraph();
		Map<String, Node> nodeIds = new HashMap<String, Node>();
		
		HashMap<String, String> users = getUsers();
		try {
			if(!involvedUsers.isEmpty()) {
				for(String userUri : involvedUsers) {
					if(users.containsKey(userUri)) {
						Node userNode = graph.createNode(); 
						if(showUserNames) {
							graph.setNodeName(userNode, users.get(userUri));
						}
						else {
							graph.setNodeName(userNode, userUri);
						}
						
						nodeIds.put(userUri, userNode);
					}
				}
			}
			else {
				//create nodes for all users
				for(Map.Entry<String, String> user : users.entrySet()) {
					Node userNode = graph.createNode(); 
					if(showUserNames) {
						graph.setNodeName(userNode, user.getValue());
					}
					else {
						graph.setNodeName(userNode, user.getKey());
					}
					
					nodeIds.put(user.getKey(), userNode);
				}
			}
		}
		catch (Exception e) {
			throw new AdapterException("Could not parse users");
		}
		
		try {
			//Iterate through each user, get their created resources. Then get the other users that interacted with those and draw edges from them to the user
			for(Map.Entry<String, Node> user : nodeIds.entrySet()) { 
				ArrayList<String> resources = getCreatedResources(user.getKey());
				ArrayList<String> interactingUsers = getInteractingUsers(resources);
				
				for(String interactingUser : interactingUsers) {
					//System.out.println("USERS: " + user.getKey() + " " + interactingUser);
					if(nodeIds.containsKey(interactingUser)) {
						graph.createEdge(nodeIds.get(interactingUser), user.getValue());
					}
				}
			}
		}
		catch (Exception e) {
			throw new AdapterException("Could not parse resources");
		}
		
		return graph;
	}
	
	/**
	 * Queries all usernames from the LMS Triplestore
	 * @return A HashMap of all profiles with their urls as keys and their names as values
	 */
	private HashMap<String, String> getUsers() {
				
		String usersQueryString = 
			    "PREFIX w3: <http://www.w3.org/2000/01/rdf-schema#> " +
			    "PREFIX leip: <http://uni-leipzig.de/tech4comp/ontology/> " +
			    "SELECT DISTINCT ?profile ?user " +
			    "WHERE { " +
			    " GRAPH <https://triplestore.tech4comp.dbis.rwth-aachen.de/LMSData/data> { " +
			    "      ?profile a leip:user . " +
			    "      ?profile w3:label ?user . " +
			    "      } " +
			    "	}";
		
{'fraction_non_alphanumeric': 0.13066343042071196, 'fraction_numerical': 0.0036407766990291263, 'mean_word_length': 3.472636815920398, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5567852', 'n_tokens_mistral': 3597, 'n_tokens_neox': 3046, 'n_words': 689}