<commit_before>package fr.inria.diverse.k3.al.annotationprocessor

import org.eclipse.xtend.lib.macro.CodeGenerationContext
import java.util.List
import java.util.Map
import org.eclipse.xtend.lib.macro.file.Path
import java.util.Properties
import org.eclipse.xtend.lib.macro.TransformationContext
import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration
import java.util.ArrayList
import java.io.IOException

/**
 * This class is in charge of building and updating the property file that list all the Aspect classes for a given Class
 * It mus tbe called within the doGenerateCode() of the ClassProcessor
 * This builder will do nothing if called without annotated element
 */
class AspectMappingBuilder {


	// list of annoted classes
	var List<? extends MutableClassDeclaration> classes;

	// destination properties file
	var Path targetFilePath

	/** internal map */
	private val Map<String, List<String>> mapping = newHashMap


	/** Rebuild mapping from existing property file*/
	public def void readCurrentMapping(List<? extends MutableClassDeclaration> classes, extension TransformationContext context){
		this.classes = classes
		//this.context = context
		if (classes.size > 0) {
			val filePath = classes.head.compilationUnit.filePath
			targetFilePath = filePath.projectFolder.append('''/META-INF/xtend-gen/«filePath.projectFolder.lastSegment».k3_aspect_mapping.properties''')
		}
		if (classes.size > 0) {
			val Properties properties = new Properties();
			if(targetFilePath.exists){
				try {
					properties.load(targetFilePath.contentsAsStream)
					properties.forEach[propKey, commaSeparatedPropvalues|
						val propValues = (commaSeparatedPropvalues as String).split(",").map[s | s.trim]
						propValues.forEach[propValue | addMapping(propKey as String, propValue)]
					]
				} catch (IOException e) {
					// ...
				}
			}
		}
	}

	/** try to clean unused mappings */
	public def void cleanUnusedMapping(extension TransformationContext context){
		if (classes.size > 0) {

			val List<String> keytoRemove = new ArrayList<String>
			mapping.forEach[key, valueList|
				// recompute a value list that contains only types that are found in the classpath
				val List<String> newValueList = valueList.filter[value | findTypeGlobally(value)!==null].toList
				mapping.put(key, newValueList)
				if(newValueList.size == 0){
					keytoRemove.add(key)
				}
			]
			keytoRemove.forEach[key | mapping.remove(key)]
		}
	}

	public def void addMappingForAnnotatedSourceElements(){
		for (annotatedSourceElement : classes) {
			val aspectizedClassType = Helper::getAnnotationAspectType(annotatedSourceElement)

			if (aspectizedClassType !== null) {
				addMapping(aspectizedClassType.name, annotatedSourceElement.qualifiedName)
			}
		}

	}

	public def void writePropertyFile(extension CodeGenerationContext context){
		if (classes.size > 0) {
			var buf = ''''''
			for (entrySet : mapping.entrySet) {
				buf = '''«buf.toString»
«entrySet.key» = «FOR aString : entrySet.value SEPARATOR ', '»«aString»«ENDFOR»'''
			}

			targetFilePath.contents = '''# List of the Java classes that have been aspectized and name of the aspect classes separated by comma
«buf.toString»'''

		}
	}

	private def void addMapping(String aspectizedClassName, String aspectClassName){
		var existingListForAspectizedElement = mapping.get(aspectizedClassName)

		if (existingListForAspectizedElement === null) {
			existingListForAspectizedElement = newArrayList
			mapping.put(aspectizedClassName, existingListForAspectizedElement)
		}
		if(!existingListForAspectizedElement.contains(aspectClassName)){
			existingListForAspectizedElement.add(aspectClassName)
		}
	}

}<commit_msg>Do not generate the .properties if no changes.<commit_after>package fr.inria.diverse.k3.al.annotationprocessor

import org.eclipse.xtend.lib.macro.CodeGenerationContext
import java.util.List
import java.util.Map
import org.eclipse.xtend.lib.macro.file.Path
import java.util.Properties
import org.eclipse.xtend.lib.macro.TransformationContext
import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration
import java.util.ArrayList
import java.io.IOException
import java.nio.file.Files
import java.nio.file.Paths

/**
 * This class is in charge of building and updating the property file that list all the Aspect classes for a given Class
 * It mus tbe called within the doGenerateCode() of the ClassProcessor
 * This builder will do nothing if called without annotated element
 */
class AspectMappingBuilder {


	// list of annoted classes
	var List<? extends MutableClassDeclaration> classes;

	// destination properties file
	var Path targetFilePath

	/** internal map */
	private val Map<String, List<String>> mapping = newHashMap


	/** Rebuild mapping from existing property file*/
	public def void readCurrentMapping(List<? extends MutableClassDeclaration> classes, extension TransformationContext context){
		this.classes = classes
		//this.context = context
		if (classes.size > 0) {
			val filePath = classes.head.compilationUnit.filePath
			targetFilePath = filePath.projectFolder.append('''/META-INF/xtend-gen/«filePath.projectFolder.lastSegment».k3_aspect_mapping.properties''')
		}
		if (classes.size > 0) {
			val Properties properties = new Properties();
			if(targetFilePath.exists){
				try {
					properties.load(targetFilePath.contentsAsStream)
					properties.forEach[propKey, commaSeparatedPropvalues|
						val propValues = (commaSeparatedPropvalues as String).split(",").map[s | s.trim]
						propValues.forEach[propValue | addMapping(propKey as String, propValue)]
					]
				} catch (IOException e) {
					// ...
				}
			}
		}
	}

	/** try to clean unused mappings */
	public def void cleanUnusedMapping(extension TransformationContext context){
		if (classes.size > 0) {

			val List<String> keytoRemove = new ArrayList<String>
			mapping.forEach[key, valueList|
				// recompute a value list that contains only types that are found in the classpath
				val List<String> newValueList = valueList.filter[value | findTypeGlobally(value)!==null].toList
				mapping.put(key, newValueList)
				if(newValueList.size == 0){
					keytoRemove.add(key)
				}
			]
			keytoRemove.forEach[key | mapping.remove(key)]
		}
	}

	public def void addMappingForAnnotatedSourceElements(){
		for (annotatedSourceElement : classes) {
			val aspectizedClassType = Helper::getAnnotationAspectType(annotatedSourceElement)

			if (aspectizedClassType !== null) {
				addMapping(aspectizedClassType.name, annotatedSourceElement.qualifiedName)
			}
		}

	}

	public def void writePropertyFile(extension CodeGenerationContext context){
		if (classes.size > 0) {
			var buf = ''''''
			for (entrySet : mapping.entrySet) {
				buf = '''«buf.toString»
«entrySet.key» = «FOR aString : entrySet.value SEPARATOR ', '»«aString»«ENDFOR»'''
			}

			val contents = '''# List of the Java classes that have been aspectized and name of the aspect classes separated by comma
«buf.toString»'''
			val oldContents = new String(Files.readAllBytes(Paths.get(targetFilePath.toURI)))
			// do not use the contents API, it raises outofsync exception in Eclipse		if (targetFilePath.contents != contents) // compare new contents and old contents before file is written
			if (oldContents != contents)
				targetFilePath.contents = contents 		
		}
	}

	private def void addMapping(String aspectizedClassName, String aspectClassName){
		var existingListForAspectizedElement = mapping.get(aspectizedClassName)

		if (existingListForAspectizedElement === null) {
			existingListForAspectizedElement = newArrayList
			mapping.put(aspectizedClassName, existingListForAspectizedElement)
		}
		if(!existingListForAspectizedElement.contains(aspectClassName)){
			existingListForAspectizedElement.add(aspectClassName)
		}
	}

}
{'fraction_non_alphanumeric': 0.09591679506933744, 'fraction_numerical': 0.0017976373908577298, 'mean_word_length': 4.551674982181041, 'pattern_counts': {'":': 0, '<': 17, '<?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': '1897534', 'n_tokens_mistral': 2503, 'n_tokens_neox': 2187, 'n_words': 610}