<commit_before>package de.stefanocke.japkit.support.el

import de.stefanocke.japkit.support.AbstractRule
import de.stefanocke.japkit.support.CodeFragmentRules
import de.stefanocke.japkit.support.ElementMatcher
import de.stefanocke.japkit.support.ElementsExtensions
import de.stefanocke.japkit.support.ExtensionRegistry
import de.stefanocke.japkit.support.GenerateClassContext
import de.stefanocke.japkit.support.MessageCollector
import de.stefanocke.japkit.support.PropertyFilter
import de.stefanocke.japkit.support.RuleFactory
import de.stefanocke.japkit.support.TypeElementNotFoundException
import de.stefanocke.japkit.support.TypeResolver
import de.stefanocke.japkit.support.TypesExtensions
import de.stefanocke.japkit.support.TypesRegistry
import de.stefanocke.japkit.util.MoreCollectionExtensions
import java.util.ArrayList
import java.util.Collections
import java.util.Set
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement
import javax.lang.model.type.TypeMirror
import org.eclipse.xtext.xbase.lib.Functions.Function0
import org.eclipse.xtext.xbase.lib.Functions.Function1

import static extension de.stefanocke.japkit.util.MoreCollectionExtensions.*

@Data
class ELVariableRule extends AbstractRule implements Function1<Object, Object>,  Function0<Object> {
	val extension ElementsExtensions elements = ExtensionRegistry.get(ElementsExtensions)

	extension TypesExtensions types = ExtensionRegistry.get(TypesExtensions)
	val extension MessageCollector = ExtensionRegistry.get(MessageCollector)
	extension GenerateClassContext = ExtensionRegistry.get(GenerateClassContext)
	extension ELSupport = ExtensionRegistry.get(ELSupport)
	val extension RuleFactory = ExtensionRegistry.get(RuleFactory)
	val extension TypeResolver = ExtensionRegistry.get(TypeResolver)

	String name
	boolean ifEmpty
	boolean isFunction
	String triggerAv
	String expr
	String lang
	Class<?> type
	boolean setInShadowAnnotation
	Set<TypeMirror> requiredTriggerAnnotation
	CodeFragmentRules codeFragments

	//TODO: Das könnten auch direkt PropertyFilter sein, aber im Moment ist die Trigger Anntoation Teil ihres State...
	AnnotationMirror[] propertyFilterAnnotations

	//TODO: TypeQuery Rule?
	AnnotationMirror typeQuery
	TypeMirror annotationToRetrieve
	ElementMatcher matcher

	new(AnnotationMirror elVarAnnotation) {
		super(elVarAnnotation, null)
		_name = elVarAnnotation.value("name", String);
		
		_ifEmpty = elVarAnnotation.value("ifEmpty", Boolean);
		_isFunction = elVarAnnotation.value("isFunction", Boolean);
		_triggerAv = elVarAnnotation.value("triggerAV", String);
		_expr = elVarAnnotation.value("expr", String);
		_lang = elVarAnnotation.value("lang", String);
		_type = Class.forName(elVarAnnotation.value("type", TypeMirror).asElement.qualifiedName.toString);

		_setInShadowAnnotation = elVarAnnotation.value("setInShadowAnnotation", Boolean);

		//TODO: Use Rule factory. But this is not possible, if we use triggerAnnotation. Reconsider...
		_propertyFilterAnnotations = elVarAnnotation.value("propertyFilter", typeof(AnnotationMirror[]))

		_typeQuery = elVarAnnotation.value("typeQuery", AnnotationMirror)

		_annotationToRetrieve = elVarAnnotation.value("annotation", TypeMirror)

		_matcher = elVarAnnotation.value("matcher", typeof(AnnotationMirror[])).map[createElementMatcher].singleValue
		
		_requiredTriggerAnnotation = elVarAnnotation.value("requiredTriggerAnnotation", typeof(TypeMirror[])).toSet

		val codeFragmentAnnotations = elVarAnnotation.value("code", typeof(AnnotationMirror[]))
		
		_codeFragments = if(codeFragmentAnnotations.empty) null else new CodeFragmentRules(codeFragmentAnnotations)
	}

	def void putELVariable() {
		
			if (isFunction) {
				valueStack.put(name, this)
			} else {
				val exisitingValue = valueStack.get(name)
				if(ifEmpty && exisitingValue!==null && !exisitingValue.emptyVar) return
				
				val value = eval(currentSrc)
				valueStack.put(name, value)
			}
	}
	
	//TODO: What about empty collections and arrays?
	
	def dispatch boolean isEmptyVar(String string) {
		string.empty
	}
	
	def dispatch boolean isEmptyVar(CharSequence cs) {
		cs.length == 0
	}
	
	def dispatch boolean isEmptyVar(Object object) {
		false
	}<commit_msg>ifEmpty to support collections, maps and arrays<commit_after>package de.stefanocke.japkit.support.el

import de.stefanocke.japkit.support.AbstractRule
import de.stefanocke.japkit.support.CodeFragmentRules
import de.stefanocke.japkit.support.ElementMatcher
import de.stefanocke.japkit.support.ElementsExtensions
import de.stefanocke.japkit.support.ExtensionRegistry
import de.stefanocke.japkit.support.GenerateClassContext
import de.stefanocke.japkit.support.MessageCollector
import de.stefanocke.japkit.support.PropertyFilter
import de.stefanocke.japkit.support.RuleFactory
import de.stefanocke.japkit.support.TypeElementNotFoundException
import de.stefanocke.japkit.support.TypeResolver
import de.stefanocke.japkit.support.TypesExtensions
import de.stefanocke.japkit.support.TypesRegistry
import de.stefanocke.japkit.util.MoreCollectionExtensions
import java.util.ArrayList
import java.util.Collections
import java.util.Set
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement
import javax.lang.model.type.TypeMirror
import org.eclipse.xtext.xbase.lib.Functions.Function0
import org.eclipse.xtext.xbase.lib.Functions.Function1

import static extension de.stefanocke.japkit.util.MoreCollectionExtensions.*
import java.util.Collection
import java.util.Map
import java.util.Arrays
import java.lang.reflect.Array

@Data
class ELVariableRule extends AbstractRule implements Function1<Object, Object>,  Function0<Object> {
	val extension ElementsExtensions elements = ExtensionRegistry.get(ElementsExtensions)

	extension TypesExtensions types = ExtensionRegistry.get(TypesExtensions)
	val extension MessageCollector = ExtensionRegistry.get(MessageCollector)
	extension GenerateClassContext = ExtensionRegistry.get(GenerateClassContext)
	extension ELSupport = ExtensionRegistry.get(ELSupport)
	val extension RuleFactory = ExtensionRegistry.get(RuleFactory)
	val extension TypeResolver = ExtensionRegistry.get(TypeResolver)

	String name
	boolean ifEmpty
	boolean isFunction
	String triggerAv
	String expr
	String lang
	Class<?> type
	boolean setInShadowAnnotation
	Set<TypeMirror> requiredTriggerAnnotation
	CodeFragmentRules codeFragments

	//TODO: Das könnten auch direkt PropertyFilter sein, aber im Moment ist die Trigger Anntoation Teil ihres State...
	AnnotationMirror[] propertyFilterAnnotations

	//TODO: TypeQuery Rule?
	AnnotationMirror typeQuery
	TypeMirror annotationToRetrieve
	ElementMatcher matcher

	new(AnnotationMirror elVarAnnotation) {
		super(elVarAnnotation, null)
		_name = elVarAnnotation.value("name", String);
		
		_ifEmpty = elVarAnnotation.value("ifEmpty", Boolean);
		_isFunction = elVarAnnotation.value("isFunction", Boolean);
		_triggerAv = elVarAnnotation.value("triggerAV", String);
		_expr = elVarAnnotation.value("expr", String);
		_lang = elVarAnnotation.value("lang", String);
		_type = Class.forName(elVarAnnotation.value("type", TypeMirror).asElement.qualifiedName.toString);

		_setInShadowAnnotation = elVarAnnotation.value("setInShadowAnnotation", Boolean);

		//TODO: Use Rule factory. But this is not possible, if we use triggerAnnotation. Reconsider...
		_propertyFilterAnnotations = elVarAnnotation.value("propertyFilter", typeof(AnnotationMirror[]))

		_typeQuery = elVarAnnotation.value("typeQuery", AnnotationMirror)

		_annotationToRetrieve = elVarAnnotation.value("annotation", TypeMirror)

		_matcher = elVarAnnotation.value("matcher", typeof(AnnotationMirror[])).map[createElementMatcher].singleValue
		
		_requiredTriggerAnnotation = elVarAnnotation.value("requiredTriggerAnnotation", typeof(TypeMirror[])).toSet

		val codeFragmentAnnotations = elVarAnnotation.value("code", typeof(AnnotationMirror[]))
		
		_codeFragments = if(codeFragmentAnnotations.empty) null else new CodeFragmentRules(codeFragmentAnnotations)
	}

	def void putELVariable() {
		
			if (isFunction) {
				valueStack.put(name, this)
			} else {
				val exisitingValue = valueStack.get(name)
				if(ifEmpty && exisitingValue!==null && !exisitingValue.emptyVar) return
				
				val value = eval(currentSrc)
				valueStack.put(name, value)
			}
	}
	
	//TODO: What about empty collections and arrays?
	
	def dispatch boolean isEmptyVar(String string) {
		string.empty
	}
	
	def dispatch boolean isEmptyVar(CharSequence cs) {
		cs.length == 0
	}
	
	def dispatch boolean isEmptyVar(Collection<?> c) {
		c.empty
	}
	
	def dispatch boolean isEmptyVar(Map<?, ?> m) {
		m.empty
	}
	
	def dispatch boolean isEmptyVar(Iterable<?> i) {
		i.empty
	}
	
	def dispatch boolean isEmptyVar(Object object) {
		if(object.class.array){
			Array.getLength(object) == 0
		} else {
			false
		}
	}
{'fraction_non_alphanumeric': 0.08783708179478572, 'fraction_numerical': 0.0012308380888441312, 'mean_word_length': 6.099285146942018, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 14, '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': '3408146', 'n_tokens_mistral': 2773, 'n_tokens_neox': 2566, 'n_words': 534}