<commit_before>package org.mitre.neoprofiler.profiler;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.mitre.neoprofiler.NeoProfiler;
import org.mitre.neoprofiler.profile.NeoProfile;
import org.mitre.neoprofiler.profile.ParameterizedNeoProfile;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;

/**
 * Profiler for a particular relationship type.
 * @author moxious
 */
public class RelationshipTypeProfiler extends QueryRunner implements Profiler {
	String type = null;
	
	class RelationshipTypeProfile extends ParameterizedNeoProfile {
		public RelationshipTypeProfile(String type) { 
			name="RelationshipTypeProfile"; 
			description="Profile of relationships of type '" + type + "'";
			setParameter("type", type);			
		}
	}
	
	public RelationshipTypeProfiler(String type) {
		this.type = type;
	}
	
	public NeoProfile run(NeoProfiler parent) {		
		NeoProfile p = new RelationshipTypeProfile(type);
		
		Object result = runQuerySingleResult(parent, "match n-[r:`" + type + "`]->m return count(r) as c", "c");
		p.addObservation("Total relationships", ""+result);
		
		Map<String,List<Object>> ret = runQueryComplexResult(parent,
				"match n-[r:`" + type + "`]->m return n as left, m as right limit 50", 
				"right", "left");
		
		try ( Transaction tx = parent.getDB().beginTx() ) {
			HashSet<String> labels = new HashSet<String>();
			
			for(Object headNode : ret.get("left")) {
				Iterator<Label> headLabels = ((Node)headNode).getLabels().iterator();
				while(headLabels.hasNext()) labels.add(headLabels.next().name());				
			}
			
			p.addObservation("domain", labels); 
						
			labels = new HashSet<String>();
			for(Object tailNode : ret.get("right")) {
				Iterator<Label> tailLabels = ((Node)tailNode).getLabels().iterator();
				while(tailLabels.hasNext()) labels.add(tailLabels.next().name());				<commit_msg>Added sample properties of relationships<commit_after>package org.mitre.neoprofiler.profiler;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.mitre.neoprofiler.NeoProfiler;
import org.mitre.neoprofiler.profile.NeoProfile;
import org.mitre.neoprofiler.profile.NeoProperty;
import org.mitre.neoprofiler.profile.ParameterizedNeoProfile;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.Transaction;

/**
 * Profiler for a particular relationship type.
 * @author moxious
 */
public class RelationshipTypeProfiler extends QueryRunner implements Profiler {
	String type = null;
	
	class RelationshipTypeProfile extends ParameterizedNeoProfile {
		public RelationshipTypeProfile(String type) { 
			name="Relationships Typed '" + type + "'"; 
			description="Profile of relationships of type '" + type + "'";
			setParameter("type", type);			
			setParameter("sampleSize", new Integer(100));
		}
	}
	
	public RelationshipTypeProfiler(String type) {
		this.type = type;
	}
	
	public NeoProfile run(NeoProfiler parent) {		
		RelationshipTypeProfile p = new RelationshipTypeProfile(type);
		
		int sampleSize = (Integer)p.getParameter("sampleSize");
		
		Object result = runQuerySingleResult(parent, "match n-[r:`" + type + "`]->m return count(r) as c", "c");
		p.addObservation("Total relationships", ""+result);
		
		Map<String,List<Object>> ret = runQueryComplexResult(parent,
				"match n-[r:`" + type + "`]->m return n as left, m as right, r as rel limit " + sampleSize, 
				"right", "left", "rel");
		
		try ( Transaction tx = parent.getDB().beginTx() ) {
			HashSet<NeoProperty> props = new HashSet<NeoProperty>();
			HashMap<String,Integer> seen = new HashMap<String,Integer>();
			
			for(Object r : ret.get("rel")) { 				
				for(NeoProperty prop : getSampleProperties(parent, (Relationship)r)) {
					String key = prop.toString();
					
					// Increment counter.
					if(!seen.containsKey(key)) { seen.put(key, 1); }
					else { seen.put(key, seen.get(key) + 1); continue; } 					
					
					props.add(prop);
				}							
			}

			// If a property was seen in some (but not all) samples, then it's optional.
			for(NeoProperty prop : props) { 
				int count = seen.get(prop.toString());
				System.out.println("For relationship " + type + " property " + prop + " seen " + count + " of " + sampleSize + " times.");
				if(count < sampleSize) prop.setOptional(true);
				else prop.setOptional(false); 
			}
			
			p.addObservation("Sample properties", props);
			
			HashSet<String> labels = new HashSet<String>();
			
			for(Object headNode : ret.get("left")) {
				Iterator<Label> headLabels = ((Node)headNode).getLabels().iterator();
				while(headLabels.hasNext()) labels.add(headLabels.next().name());				
			}
			
			p.addObservation("domain", labels); 
						
			labels = new HashSet<String>();
			for(Object tailNode : ret.get("right")) {
				Iterator<Label> tailLabels = ((Node)tailNode).getLabels().iterator();
				while(tailLabels.hasNext()) labels.add(tailLabels.next().name());				
{'fraction_non_alphanumeric': 0.1403680501174628, 'fraction_numerical': 0.00274079874706343, 'mean_word_length': 4.145015105740181, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '7323200', 'n_tokens_mistral': 1838, 'n_tokens_neox': 1574, 'n_words': 351}