<commit_before>package io.badgeup.sponge.event;

import java.util.List;
import java.util.UUID;

import org.json.JSONArray;
import org.json.JSONObject;
import org.spongepowered.api.data.DataSerializable;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.text.Text;

import io.badgeup.sponge.Util;

public class BadgeUpEvent {

	private String key;

	private UUID subject;

	// user provided data
	private JSONObject data;
	
	// BadgeUp event options
	private JSONObject options;

	private Modifier modifier;

	/**
	 * Constructor for a BadgeUp event
	 * @param key the identifying string for this type of event
	 * @param subject the subject string identifying the user that caused this event
	 * @param modifier the metric impact this event will have 
	 */
	public BadgeUpEvent(String key, UUID subject, Modifier modifier) {
		this.key = key;
		this.subject = subject;
		this.modifier = modifier;
		this.data = new JSONObject();
		this.options = new JSONObject();
	}
	
	public void setKey(String key) {
		this.key = key;
	}

	/**
	 * Add a custom key/value data pair
	 * @param key
	 * @param value
	 */
	public void addDataEntry(final String key, Object value) {
		if(value instanceof DataSerializable) {
			if(value instanceof Player) {
				return;
			} else if(value instanceof Text) {
				value = ((Text) value).toPlain();
			} else {
				JSONObject serializedObject = Util.dataContainerToJSONObject(((DataSerializable) value).toContainer());
				Util.cleanData(serializedObject);
				value = serializedObject;
			}
		} else {
			if(value instanceof Enum) {
				value = value.toString();
			} else if(value instanceof List) {
				JSONArray array = new JSONArray();
				for(Object entry : (List) value) {
					if(!(entry instanceof DataSerializable)) {
						return;
					}
					JSONObject serializedObject = Util.dataContainerToJSONObject(((DataSerializable) entry).toContainer());
					Util.cleanData(serializedObject);
					array.put(serializedObject);
				}
				value = array;
			} else {
				return;
			}
		}
		data.put(key, value);
	}

	/**
	 * Marks the event to be discarded (not stored) after it is processed
	 */
	public void setDiscardable(boolean discardable) {
		if (discardable) {
			this.options.put("discard", discardable);
		} else {
			this.options.remove("discard");
		}
	}
	
	public JSONObject build() {
		return new JSONObject()
				.put("key", key)
				.put("subject", subject.toString())
				.put("data", data)
				.put("options", options)
				.put("modifier", new JSONObject().put(modifier.getOperation().getName(), modifier.getValue()));
	}
	<commit_msg>Don't include data w/o any toString serialization<commit_after>package io.badgeup.sponge.event;

import java.lang.reflect.Method;
import java.util.List;
import java.util.UUID;

import org.json.JSONArray;
import org.json.JSONObject;
import org.spongepowered.api.data.DataSerializable;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.cause.Cause;
import org.spongepowered.api.text.Text;

import io.badgeup.sponge.Util;

public class BadgeUpEvent {

	private String key;

	private UUID subject;

	// user provided data
	private JSONObject data;

	// BadgeUp event options
	private JSONObject options;

	private Modifier modifier;

	/**
	 * Constructor for a BadgeUp event
	 * 
	 * @param key
	 *            the identifying string for this type of event
	 * @param subject
	 *            the subject string identifying the user that caused this event
	 * @param modifier
	 *            the metric impact this event will have
	 */
	public BadgeUpEvent(String key, UUID subject, Modifier modifier) {
		this.key = key;
		this.subject = subject;
		this.modifier = modifier;
		this.data = new JSONObject();
		this.options = new JSONObject();
	}

	public void setKey(String key) {
		this.key = key;
	}

	/**
	 * Add a custom key/value data pair
	 * 
	 * @param key
	 * @param value
	 */
	@SuppressWarnings("rawtypes")
	public void addDataEntry(final String key, Object value) {
		if (value instanceof Player || value instanceof Cause || value instanceof Class) {
			return;
		}

		if (value instanceof DataSerializable) {
			if (value instanceof Text) {
				value = ((Text) value).toPlain();
			} else {
				JSONObject serializedObject = Util.dataContainerToJSONObject(((DataSerializable) value).toContainer());
				Util.cleanData(serializedObject);
				value = serializedObject;
			}
		} else {
			if (value instanceof List) {
				JSONArray array = new JSONArray();
				for (Object entry : (List) value) {
					if (!(entry instanceof DataSerializable)) {
						return;
					}
					JSONObject serializedObject = Util
							.dataContainerToJSONObject(((DataSerializable) entry).toContainer());
					Util.cleanData(serializedObject);
					array.put(serializedObject);
				}
				value = array;
			} else {
				Method toStringMethod;
				try {
					toStringMethod = value.getClass().getMethod("toString");
				} catch (NoSuchMethodException e) {
					// Can't be thrown since every class has a toString method
					// through Object
					return;
				}
				if (toStringMethod.getDeclaringClass() == Object.class) {
					// toString has not been implemented and will only produce
					// the class name + the object hash
					// this is useless, so discard it
					return;
				}
			}
		}
		data.put(key, value);
	}

	/**
	 * Marks the event to be discarded (not stored) after it is processed
	 */
	public void setDiscardable(boolean discardable) {
		if (discardable) {
			this.options.put("discard", discardable);
		} else {
			this.options.remove("discard");
		}
	}

	public JSONObject build() {
		return new JSONObject().put("key", key).put("subject", subject.toString()).put("data", data)
				.put("options", options)
				.put("modifier", new JSONObject().put(modifier.getOperation().getName(), modifier.getValue()));
	}

{'fraction_non_alphanumeric': 0.11340030648731483, 'fraction_numerical': 0.0, 'mean_word_length': 3.456752655538695, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '6436301', 'n_tokens_mistral': 2058, 'n_tokens_neox': 1723, 'n_words': 491}