All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fhoster.livebase.BlueprintAnnotationProcessor.xtend Maven / Gradle / Ivy

/**
 *   Copyright 2021 Fhoster srl
 * 
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.fhoster.livebase

import com.fhoster.blueprintassisted.BlpServiceReference
import java.io.PrintWriter
import java.util.Collection
import javax.lang.model.element.Element
import javax.lang.model.element.ExecutableElement
import javax.tools.StandardLocation
import java.util.List

abstract class BlueprintAnnotationProcessor extends AnnotationProcessor {

    UniqueIdGenerator generator
    String uniqueId
    
    new(UniqueIdGenerator generator) {
        this.generator = generator
    }
    
	protected def generateBlueprintXML(Element c, String serviceProperties) {
		val annot = c.getAnnotation(supportedAnnotation)
		val className = c.toString
		val beanId = c.beanID
		val serviceId = serviceID(className)
		val onlyConstructor = c.inectableConstructor
		var String elementInterface = null
		if(c.interfaces.empty) {
			elementInterface = c.superclass.toString
		} else{
			elementInterface = c.interfaces.head.toString
		}

		var fileName = '''OSGI-INF/blueprint/«className».blueprint.xml'''

		val hasDraft = annot.annotationType.declaredMethods.filter[name == "draft"]
		if(hasDraft.size > 0) {
			val draft = hasDraft.head.invoke(annot) as Boolean
			if(draft)
				fileName += ".draft"
		}

		val location = StandardLocation.SOURCE_OUTPUT
		val file = createResource(location, fileName)

		uniqueId = generator.getUniqueId()
		
        val predefinedServiceReferences = newArrayList
        predefinedServiceReferences.addAll(onlyConstructor.assistedBlueprintReferences)
        predefinedServiceReferences.addAll(knownBlueprintReferences)
        
		val constructorArgs = processElementConstructor(onlyConstructor, predefinedServiceReferences)
		val out = new PrintWriter(file.openOutputStream)
		val part = '''
			
				
				
				«predefinedServiceReferences.filter[it.used].map[it.xmlSnippet].join('\n')»
									
				
					«constructorArgs.join('\n')»
				
				
			
				
					«serviceProperties»
				
					
				
			'''
		out.write(part)
		out.close
	}
    
    def Collection getAssistedBlueprintReferences(ExecutableElement onlyConstructor) {
        onlyConstructor.parameters
            .filter[it.getAnnotation(BlpServiceReference)!==null]
            .map[annotated|
                val annotation=annotated.getAnnotation(BlpServiceReference)
                var refId = if (annotation.id != "") annotation.id else '''assistedReference«uniqueId»'''
                
                new BlueprintReference(annotated.asType.toString,
                '''''', 
                '''
                
                ''',
                annotated.annotationMirrors.map[toString].toList 
                )].toList
    }
    
	protected def serviceID(String className) {
		'''sid.«className.toLowerCase»'''
	}

	protected def beanID(Element c) {
		'''bid.«c.toString.toLowerCase»'''
	}

	private def getKnownBlueprintReferences() {
		#[
			new BlueprintReference("org.osgi.framework.BundleContext", 
			'''''', ''''''),
			new BlueprintReference("com.fhoster.livebase.cloudlet.CloudletDataSource", 
			'''''','''
				
			'''),
			new BlueprintReference("javax.sql.DataSource", 
			'''''', '''
				
			'''),
			new BlueprintReference("com.fhoster.livebase.cloudlet.CloudletMailSystem", 
			'''''','''
				
			'''),
			new BlueprintReference("com.fhoster.livebase.cloudlet.CloudletMemberManager", 
			'''''','''
				
			'''),
			new BlueprintReference("com.fhoster.livebase.cloudlet.CloudletIdGenerator", 
			'''''', '''
				
			'''),
			new BlueprintReference("com.fhoster.livebase.cloudlet.EntitySessionFactory", 
			'''''', '''
				
			'''),
			new BlueprintReference("com.fhoster.livebase.cloudlet.CloudletEntitySessionFactory", 
			'''''', '''
				
			'''),
			new BlueprintReference("com.fhoster.livebase.cloudlet.CloudletSessionFactory", 
			'''''', '''
				
			'''),
			new BlueprintReference("com.fhoster.livebase.cloudlet.EntityLockManager", 
			'''''', '''
				
			'''),
			new BlueprintReference("com.fhoster.livebase.cloudlet.SpiCloudletSMSSender", 
			'''''', '''
				
			'''),
			new BlueprintReference("com.fhoster.livebase.cloudlet.__CurrentUserLoader",
            '''''', '''
                
            ''')
		]
	}

	private def processElementConstructor(ExecutableElement constructor,
		Iterable references) {
		val constructorArgs = newArrayList()
		
		for (t : constructor.parameters) {
			val reference = references.findFirst[ br |
			    if (br.name != t.asType.toString) return false
			    
			    val filter = t.annotationMirrors.map[toString].findFirst[am | br.filters.contains(am)]
			    if (filter !== null) return true
			    
			    //to manage known types without annotation
			    if (br.filters.empty) return true
			    
    		    return false
			]
			if(reference !== null) {
				reference.used = true
				constructorArgs.add(reference.argumentSnippet)
			} else {
				constructorArgs.add('''''')
			}
		}
		constructorArgs
	}

}

class BlueprintReference {
	public String name
	public String xmlSnippet
	public String argumentSnippet
	public List filters
	public boolean used

	new(String name, String argumentSnippet, String xmlSnippet) {
		this(name, argumentSnippet, xmlSnippet, #[])
	}
	
	new(String name, String argumentSnippet, String xmlSnippet, List filters) {
        this.name = name
        this.argumentSnippet = argumentSnippet
        this.xmlSnippet = xmlSnippet
        this.filters = filters
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy