/**
 * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0 
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 * 
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *         Florian Pirchner - Initial implementation
 */
package org.eclipse.osbp.dsl.entity.xtext.jvmmodel

import com.google.inject.Inject
import java.util.List
import javax.persistence.AssociationOverride
import javax.persistence.AssociationOverrides
import javax.persistence.AttributeOverride
import javax.persistence.AttributeOverrides
import javax.persistence.Basic
import javax.persistence.Cacheable
import javax.persistence.CascadeType
import javax.persistence.Column
import javax.persistence.DiscriminatorColumn
import javax.persistence.DiscriminatorType
import javax.persistence.DiscriminatorValue
import javax.persistence.ElementCollection
import javax.persistence.Embeddable
import javax.persistence.Embedded
import javax.persistence.Entity
import javax.persistence.EntityListeners
import javax.persistence.FetchType
import javax.persistence.GeneratedValue
import javax.persistence.Id
import javax.persistence.Index
import javax.persistence.Inheritance
import javax.persistence.InheritanceType
import javax.persistence.JoinColumn
import javax.persistence.Lob
import javax.persistence.ManyToOne
import javax.persistence.MappedSuperclass
import javax.persistence.OneToMany
import javax.persistence.OneToOne
import javax.persistence.Table
import javax.persistence.Temporal
import javax.persistence.TemporalType
import javax.persistence.Transient
import javax.persistence.Version
import org.eclipse.osbp.dsl.entity.xtext.extensions.AnnotationExtension
import org.eclipse.osbp.dsl.entity.xtext.extensions.ModelExtensions
import org.eclipse.osbp.dsl.entity.xtext.extensions.NamingExtensions
import org.eclipse.osbp.dsl.entity.xtext.util.PersistenceNamingUtils
import org.eclipse.osbp.dsl.semantic.common.types.LAttributeMatchingConstraint
import org.eclipse.osbp.dsl.semantic.common.types.LDataType
import org.eclipse.osbp.dsl.semantic.common.types.LReference
import org.eclipse.osbp.dsl.semantic.common.types.LResultFilters
import org.eclipse.osbp.dsl.semantic.entity.LBean
import org.eclipse.osbp.dsl.semantic.entity.LBeanAttribute
import org.eclipse.osbp.dsl.semantic.entity.LBeanFeature
import org.eclipse.osbp.dsl.semantic.entity.LBeanReference
import org.eclipse.osbp.dsl.semantic.entity.LDiscriminatorType
import org.eclipse.osbp.dsl.semantic.entity.LEntity
import org.eclipse.osbp.dsl.semantic.entity.LEntityAttribute
import org.eclipse.osbp.dsl.semantic.entity.LEntityInheritanceStrategy
import org.eclipse.osbp.dsl.semantic.entity.LEntityReference
import org.eclipse.osbp.dsl.semantic.entity.LOperation
import org.eclipse.osbp.dsl.semantic.entity.LTablePerClassStrategy
import org.eclipse.osbp.dsl.semantic.entity.LTablePerSubclassStrategy
import org.eclipse.osbp.jpa.services.listener.EntityInfoListener
import org.eclipse.osbp.runtime.common.annotations.AsGrid
import org.eclipse.osbp.runtime.common.annotations.AsKanbanOrdering
import org.eclipse.osbp.runtime.common.annotations.AsKanbanState
import org.eclipse.osbp.runtime.common.annotations.AsTable
import org.eclipse.osbp.runtime.common.annotations.Dispose
import org.eclipse.osbp.runtime.common.annotations.DomainDescription
import org.eclipse.osbp.runtime.common.annotations.DomainKey
import org.eclipse.osbp.runtime.common.annotations.Filter
import org.eclipse.osbp.runtime.common.annotations.OnKanbanCard
import org.eclipse.osbp.runtime.common.annotations.Range
import org.eclipse.osbp.runtime.common.annotations.TargetEnumConstraint
import org.eclipse.osbp.runtime.common.annotations.TargetEnumConstraints
import org.eclipse.osbp.runtime.common.annotations.UIGroup
import org.eclipse.osbp.runtime.common.annotations.UniqueEntry
import org.eclipse.persistence.annotations.Noncacheable
import org.eclipse.xtext.common.types.JvmAnnotationReference
import org.eclipse.xtext.common.types.JvmAnnotationTarget
import org.eclipse.xtext.common.types.JvmField
import org.eclipse.xtext.common.types.JvmGenericType
import org.eclipse.xtext.common.types.JvmOperation
import org.eclipse.xtext.common.types.util.TypeReferences
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
import org.eclipse.osbp.runtime.common.annotations.BeanOnTab
import org.eclipse.osbp.runtime.common.annotations.Hidden
import org.eclipse.osbp.runtime.common.annotations.ReadOnly
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.osbp.runtime.common.annotations.SideKick
import javax.persistence.GenerationType

/** 
 * This class is responsible to generate the Annotations defined in the entity model
 */
class AnnotationCompiler extends org.eclipse.osbp.dsl.common.xtext.jvmmodel.AnnotationCompiler {

	@Inject extension ModelExtensions
	@Inject extension JvmTypesBuilder
	@Inject extension AnnotationExtension
	@Inject extension NamingExtensions
	@Inject TypeReferences references

	def protected dispatch void internalProcessAnnotation(LBean bean, JvmGenericType jvmType) {
		jvmType.addAnnotations(bean.resolvedAnnotations.filter([!exclude]).map([annotation]))
		bean.addAnno(jvmType, bean.toAnnotation(typeof(Embeddable)))
	}

	def protected dispatch void internalProcessAnnotation(LOperation member, JvmField jvmOperation) {
		jvmOperation.addAnnotations(member.resolvedAnnotations.filter([!exclude]).map([annotation]))
	}

	def protected dispatch void internalProcessAnnotation(LEntity entity, JvmGenericType jvmType) {
		jvmType.addAnnotations(entity.resolvedAnnotations.filter([!exclude]).map([annotation]))
		if (entity.mappedSuperclass) {
			addAnno(entity, jvmType, entity.toAnnotation(typeof(MappedSuperclass)))

			val listenerAnn = entity.toAnnotation(typeof(EntityListeners))
			val listenerType = references.getTypeForName(typeof(EntityInfoListener), entity)
			listenerAnn.addAnnAttr(entity, "value", listenerType)
			addAnno(entity, jvmType, listenerAnn)

		} else {

			// @Entity
			addAnno(entity, jvmType, entity.toAnnotation(typeof(Entity)))

//			if (entity.historized) {
//				val ann = entity.toAnnotation(typeof(Customizer))
//				ann.addAnnAttr(entity, "value", references.getTypeForName(typeof(HistoryCustomizer), entity))
//			}
			if (!entity.isStrategyFromSuperPresent || entity.isStrategyPerSubclass) {

				// @Table
				val tableAnn = entity.toAnnotation(typeof(Table))
				addAnno(entity, jvmType, tableAnn)
				val schemaName = entity.toSchemaName
				if (!schemaName.nullOrEmpty) {
					tableAnn.addAnnAttr(entity, "schema", schemaName)
				}
				tableAnn.addAnnAttr(entity, "name", entity.toTableName)

				// @Index
				//
				val List<JvmAnnotationReference> collectedIndizes = newArrayList();
				for (index : entity.indexes) {
					val indexAnn = entity.toAnnotation(typeof(Index))
					addAnno(entity, jvmType, indexAnn)

					indexAnn.addAnnAttr(entity, "name", PersistenceNamingUtils::camelCaseToUpperCase(index.name))
					if (index.unique) {
						indexAnn.addAnnAttr(entity, "unique", true)
					}

					var StringBuilder propList = new StringBuilder;
					for (name : index.features.map[it.name]) {
						if (propList != null) {
							if (propList.length > 0) {
								propList.append(", ")
							}
							propList.append(PersistenceNamingUtils::camelCaseToUpperCase(name));
						}
					}
					indexAnn.addAnnAttr(entity, "columnList", propList.toString)
					collectedIndizes.add(indexAnn);
				}

				if (collectedIndizes.size > 0) {
					val JvmAnnotationReference[] result = collectedIndizes.toArray(
						newArrayOfSize(collectedIndizes.size));
					tableAnn.addAnnAttr(entity, "indexes", result)
				}
			}

			// @Inheritance
			val LEntityInheritanceStrategy strategy = entity.toInheritanceStrategy
			strategy.processInheritance(entity, jvmType)

			// @Cachable
			if (entity.cacheable) {
				addAnno(entity, jvmType, entity.toAnnotation(typeof(Cacheable)))
			}
		}
	}

	def protected dispatch void processInheritance(LTablePerClassStrategy strategy, LEntity entity,
		JvmGenericType jvmType) {

		// Process inheritance.
		// If the Entity has subclasses, setup @Inheritance
		val superType = entity.superType
		if (!entity.subTypes.empty && (superType == null || superType.checkIsMappedSuperclass)) {
			val annRef = entity.toAnnotation(typeof(Inheritance))
			annRef.addAnnAttr(entity, "strategy", InheritanceType::SINGLE_TABLE)
			addAnno(entity, jvmType, annRef)

			val discrColumn = entity.toAnnotation(typeof(DiscriminatorColumn))
			discrColumn.addAnnAttr(entity, "name", strategy.discriminatorColumn)
			discrColumn.addAnnAttr(entity, "discriminatorType", strategy.discriminatorType.toDiscriminatorType)
			addAnno(entity, jvmType, discrColumn)
		}

		// add the discriminator value only once
		if (!entity.subTypes.empty || !superType.checkIsMappedSuperclass) {
			val discrValue = entity.toAnnotation(typeof(DiscriminatorValue))
			discrValue.addAnnAttr(entity, "value", strategy.discriminatorValue)
			addAnno(entity, jvmType, discrValue)
		}

	}

	def protected dispatch void processInheritance(LTablePerSubclassStrategy strategy, LEntity entity,
		JvmGenericType jvmType) {

		// Process inheritance.
		// If the Entity has subclasses, setup @Inheritance
		val superType = entity.superType
		if (!entity.subTypes.empty && (superType == null || superType.checkIsMappedSuperclass)) {
			val annRef = entity.toAnnotation(typeof(Inheritance))
			annRef.addAnnAttr(entity, "strategy", InheritanceType::JOINED)
			addAnno(entity, jvmType, annRef)

			val discrColumn = entity.toAnnotation(typeof(DiscriminatorColumn))
			discrColumn.addAnnAttr(entity, "name", strategy.discriminatorColumn)
			discrColumn.addAnnAttr(entity, "discriminatorType", strategy.discriminatorType.toDiscriminatorType)
			addAnno(entity, jvmType, discrColumn)
		}

		// add the discriminator value only once
		if (!entity.subTypes.empty || !superType.checkIsMappedSuperclass) {
			val discrValue = entity.toAnnotation(typeof(DiscriminatorValue))
			discrValue.addAnnAttr(entity, "value", strategy.discriminatorValue)
			addAnno(entity, jvmType, discrValue)
		}
	}

	def DiscriminatorType toDiscriminatorType(LDiscriminatorType type) {
		switch (type) {
			case LDiscriminatorType::STRING:
				return DiscriminatorType::STRING
			case LDiscriminatorType::CHAR:
				return DiscriminatorType::CHAR
			case LDiscriminatorType::INTEGER:
				return DiscriminatorType::INTEGER
			default: {
			}
		}
	}

	def protected dispatch void internalProcessAnnotation(LEntityReference prop, JvmField jvmField) {
		jvmField.addAnnotations(prop.resolvedAnnotations.filter([!exclude]).map([annotation]))

		if (prop.toMany) {

			// *toMany
			if (prop.opposite.toMany) {

				// @ManyToMany
				addManyToManyAnno(prop, jvmField)
			} else {

				// @OneToMany
				addOneToManyAnno(prop, jvmField)
			}
		} else {

			// *toOne
			val opposite = prop.resolvedOpposite

			// When we have no opposite, then the master-side has no collection
			// and we assume a many-to-one relation.
			// A one-to-one relation needs an "opposite" on both sides.
			if (opposite != null && !opposite.toMany) {

				// @OneToOne
				addOneToOneAnno(prop, jvmField)
			} else {

				// @ManyToOne
				addManyToOneAnno(prop, jvmField)
			}
		}

		if (prop.resultFilters != null) {
			prop.resultFilters.addConstraintsAnno(jvmField)
		}

		// create the properties annotations
		prop.toPropertiesAnnotation(mergeKeyAndValues(prop), jvmField)

		toConstraintAnnotations(prop, jvmField)
	}

	def protected dispatch void internalProcessAnnotation(LEntityAttribute prop, JvmField jvmField) {
		jvmField.addAnnotations(prop.resolvedAnnotations.filter([!exclude]).map([annotation]))

		if (prop.transient) {
			addAnno(prop, jvmField, prop.toAnnotation(typeof(Transient)))
		} else { 
			if (prop.id) {
				jvmField.annotations += prop.toAnnotation(typeof(Id))
				var genValueAnn = prop.toAnnotation(typeof(GeneratedValue))
				genValueAnn.addAnnAttr(prop, "strategy", GenerationType.IDENTITY)
				jvmField.annotations += genValueAnn 
			} else if (prop.uuid) {
				jvmField.annotations += prop.toAnnotation(typeof(Id))
			} 
			if (prop.version) {
				jvmField.annotations += prop.toAnnotation(typeof(Version))
			}
			if (prop.attributeHidden) {
				jvmField.annotations += prop.toAnnotation(typeof(Hidden))
			} else if (prop.attributeReadOnly) {
				jvmField.annotations += prop.toAnnotation(typeof(ReadOnly))
			} 
			if (prop.toMany) {
				val ann = prop.toAnnotation(typeof(ElementCollection))
				addAnno(prop, jvmField, ann)
			} else {
			
				//
				// if the propery is a bean, then add AttributeOverride Annotations
				//
				if (prop.type instanceof LBean) {
					addAnno(prop, jvmField, prop.toAnnotation(typeof(Embedded)))
					if((prop.type as LBean).beanOnTab) {
						addAnno(prop, jvmField, prop.toAnnotation(typeof(BeanOnTab)))
					}
			
					jvmField.toAttributesOverride(prop)
				}
			
				if (prop.domainKey) {
					addAnno(prop, jvmField, prop.toAnnotation(typeof(DomainKey)))
				}
			
				if (prop.domainDescription) {
					addAnno(prop, jvmField, prop.toAnnotation(typeof(DomainDescription)))
				}
			}
			
			if (!jvmField.isColumnAnnoCreated(prop)) {
				val ann = prop.toAnnotation(typeof(Column))
				ann.addAnnAttr(prop, "name", prop.toColumnName)
				if (prop.bounds.required) {
					ann.addAnnAttr(prop, "nullable", false)
				}
				addAnno(prop, jvmField, ann)
			}
			
			if (prop.type instanceof LDataType) {
				val LDataType datatype = prop.type as LDataType
				if (datatype.date) {
					val temp = prop.toAnnotation(typeof(Temporal))
					switch (datatype.dateType) {
						case DATE:
							temp.addAnnAttr(prop, "value", TemporalType::DATE)
						case TIME:
							temp.addAnnAttr(prop, "value", TemporalType::TIME)
						case TIMESTAMP:
							temp.addAnnAttr(prop, "value", TemporalType::TIMESTAMP)
						default: {
						}
					}
					addAnno(prop, jvmField, temp)
			
				} else if (datatype.asBlob) {
					addAnno(prop, jvmField, prop.toAnnotation(typeof(Lob)))
			
					val basic = prop.toAnnotation(typeof(Basic))
					basic.addAnnAttr(prop, "fetch", FetchType::LAZY)
					addAnno(prop, jvmField, basic)
				}
			
				// add the range and filter annotation
				if (prop.isFiltering) {
					addAnno(prop, jvmField, prop.toAnnotation(typeof(Filter)))
				}
				if (prop.isRangeFiltering) {
					addAnno(prop, jvmField, prop.toAnnotation(typeof(Range)))
				}
			
				if (prop.isUniqueEntry) {
					addAnno(prop, jvmField, prop.toAnnotation(typeof(UniqueEntry)))
				}
			}
	
			if (prop.isOnKanbanCard) {
				addAnno(prop, jvmField, prop.toAnnotation(typeof(OnKanbanCard)))
			}
	
			if (prop.isAsKanbanOrdering) {
				addAnno(prop, jvmField, prop.toAnnotation(typeof(AsKanbanOrdering)))
			}
	
			if (prop.asKanbanState) {
				addAnno(prop, jvmField, prop.toAnnotation(typeof(AsKanbanState)))
			}
	
			if (prop.isGrouped) {
				val groupAnnotation = prop.toAnnotation(typeof(UIGroup))
				groupAnnotation.addAnnAttr(prop, "name", prop.groupName)
				addAnno(prop, jvmField, groupAnnotation)
			}
		}
		// create the properties annotations
		prop.toPropertiesAnnotation(mergeKeyAndValues(prop), jvmField)

		toConstraintAnnotations(prop, jvmField)
	}

	// generate Attribute overrides
	// @AttributeOverrides({
	// @AttributeOverride(name="number", column=@Column(name="ORDER_NUMBER"))
	// @AttributeOverride(name="status", column=@Column(name="ORDER_STATUS"))}
	// )
	def protected void toAttributesOverride(JvmField jvmField, LEntityAttribute prop) {

		val List<JvmAnnotationReference> collectedAttributes = newArrayList();
		val List<JvmAnnotationReference> collectedAssocations = newArrayList();

		for (LBeanFeature f : (prop.type as LBean).allFeatures.filter[!it.toMany]) {
			if (f instanceof LBeanAttribute) {

				val overrideAttributeAnno = prop.toAnnotation(typeof(AttributeOverride))
				overrideAttributeAnno.addAnnAttr(f, "name", f.toName)
				{
					val colAnno = prop.toAnnotation(typeof(Column))
					colAnno.addAnnAttr(f, "name", (prop.toName + "_" + f.toName).toUpperCase)

					overrideAttributeAnno.addAnnAttr(f, "column", colAnno)
				}

				collectedAttributes += overrideAttributeAnno;
			} else if (f instanceof LBeanReference) {
				val type = f.type
				switch (type) {
					LEntity: {
						val overrideAssociationAnno = prop.toAnnotation(typeof(AssociationOverride))
						overrideAssociationAnno.addAnnAttr(f, "name", f.toName)
						{
							val colAnno = prop.toAnnotation(typeof(JoinColumn))
							colAnno.addAnnAttr(f, "name", (prop.toName + "_" + f.toName).toUpperCase)
							overrideAssociationAnno.addAnnAttr(f, "joinColumns", colAnno)
						}

						collectedAssocations += overrideAssociationAnno;
					}
					LBean: {
						type.collectNestedAttributeOverride(collectedAttributes, f.toName,
							(prop.toName + "_" + f.toName).toUpperCase)
					}
				}
			}
		}

		if (!collectedAttributes.empty) {
			val overrideAttributesAnno = prop.toAnnotation(typeof(AttributeOverrides))
			val JvmAnnotationReference[] result = collectedAttributes.toArray(newArrayOfSize(collectedAttributes.size));
			overrideAttributesAnno.addAnnAttr(prop, "value", result)
			addAnno(prop, jvmField, overrideAttributesAnno)
		}

		if (!collectedAssocations.empty) {
			val overrideAssociationsAnno = prop.toAnnotation(typeof(AssociationOverrides))
			val JvmAnnotationReference[] result = collectedAssocations.toArray(
				newArrayOfSize(collectedAssocations.size));
			overrideAssociationsAnno.addAnnAttr(prop, "value", result)
			addAnno(prop, jvmField, overrideAssociationsAnno)
		}
	}

	/**
	 * Collects all nested embedded fields to be overridden
	 */
	def protected void collectNestedAttributeOverride(LBean bean, List<JvmAnnotationReference> collectedReferences,
		String propertyPath, String persistencePath) {
		if (bean == null) {
			return
		}

		for (LBeanFeature f : bean.allFeatures.filter[!it.toMany]) {
			if (f instanceof LBeanAttribute) {

				val overrideAttributeAnno = bean.toAnnotation(typeof(AttributeOverride))
				overrideAttributeAnno.addAnnAttr(f, "name", propertyPath + "." + f.toName)
				{
					val colAnno = bean.toAnnotation(typeof(Column))
					colAnno.addAnnAttr(f, "name", (persistencePath + "_" + f.toName).toUpperCase)
					overrideAttributeAnno.addAnnAttr(f, "column", colAnno)
				}

				collectedReferences += overrideAttributeAnno;
			} else if (f instanceof LBeanReference) {
				val oppositeType = f.opposite?.type
				val type = f.type
				switch (type) {
					LEntity: {
						// TODO implement
					}
					LBean: {
						if (oppositeType != bean) {
							type.collectNestedAttributeOverride(collectedReferences, propertyPath + "." + f.toName,
								persistencePath + "_" + f.toName.toUpperCase)
						}
					}
				}
			}
		}
	}

	def protected dispatch void internalProcessAnnotation(LBeanAttribute prop, JvmField jvmField) {
		jvmField.addAnnotations(prop.resolvedAnnotations.filter([! exclude]).map([annotation]))

		if (prop.transient) {
			jvmField.annotations += prop.toAnnotation(typeof(Transient))
		}

		var basicAdded = false;
		if (prop.type instanceof LDataType) {
			val LDataType datatype = prop.type as LDataType
			if (datatype.date) {
				addAnno(prop, jvmField, prop.toAnnotation(typeof(Basic)))
				basicAdded = true;

				val temp = prop.toAnnotation(typeof(Temporal))
				switch (datatype.dateType) {
					case DATE:
						temp.addAnnAttr(prop, "value", TemporalType::DATE)
					case TIME:
						temp.addAnnAttr(prop, "value", TemporalType::TIME)
					case TIMESTAMP:
						temp.addAnnAttr(prop, "value", TemporalType::TIMESTAMP)
				}
				addAnno(prop, jvmField, temp)
			} else if (datatype.asBlob) {
				addAnno(prop, jvmField, prop.toAnnotation(typeof(Lob)))

				val basic = prop.toAnnotation(typeof(Basic))
				basic.addAnnAttr(prop, "fetch", FetchType::LAZY)
				addAnno(prop, jvmField, basic)
				basicAdded = true;
			}

			// add the range and filter annotation
			if (prop.isFiltering) {
				prop.toAnnotation(typeof(Filter))
			}
			if (prop.isRangeFiltering) {
				prop.toAnnotation(typeof(Range))
			}
		}

		if (!basicAdded) {
			addAnno(prop, jvmField, prop.toAnnotation(typeof(Basic)))
			basicAdded = true
		}

		if (prop.toMany) {
			val ann = prop.toAnnotation(typeof(ElementCollection))
			addAnno(prop, jvmField, ann)
		}

		// create the properties annotations
		prop.toPropertiesAnnotation(mergeKeyAndValues(prop), jvmField)

		toConstraintAnnotations(prop, jvmField)
	}

	def dispatch void toConstraintAnnotations(LBeanAttribute prop, JvmField jvmField) {

		if (prop.type.validAllowed) {
			prop.toValidAnnotation(jvmField)
		}

		for (c : prop.constraints) {
			c.toConstraintAnnotation(jvmField)
		}

		if (prop.constraints.empty) {
			super.toDatatypeBasedConstraintAnnotations(prop, jvmField)
		}
	}

	def dispatch void toConstraintAnnotations(LBeanReference prop, JvmField jvmField) {

		if (prop.type instanceof LBean && !prop.bounds.toMany) {
			prop.toValidAnnotation(jvmField)
		}

		for (c : prop.constraints) {
			c.toConstraintAnnotation(jvmField)
		}
	}

	def dispatch void toConstraintAnnotations(LEntityAttribute prop, JvmField jvmField) {

		if (prop.type.validAllowed) {
			prop.toValidAnnotation(jvmField)
		}

		for (c : prop.constraints) {
			c.toConstraintAnnotation(jvmField)
		}

		if (prop.constraints.empty) {
			super.toDatatypeBasedConstraintAnnotations(prop, jvmField)
		}
	}

	def dispatch void toConstraintAnnotations(LEntityReference prop, JvmField jvmField) {

		if (prop.cascading && !prop.bounds.toMany) {
			prop.toValidAnnotation(jvmField)
		}

		for (c : prop.constraints) {
			c.toConstraintAnnotation(jvmField)
		}
	}

	def protected dispatch void internalProcessAnnotation(LBeanReference prop, JvmField jvmField) {
		jvmField.addAnnotations(prop.resolvedAnnotations.filter([!exclude]).map([annotation]))

		if (prop.type instanceof LEntity) {

			// its a reference to an entity and so we need to express the relation
			if (prop.toMany) {

				// *toMany
				if (prop.opposite.toMany) {

					// @ManyToMany
					addManyToManyAnno(prop, jvmField)
				} else {

					// @OneToMany
					addOneToManyAnno(prop, jvmField)
				}
			} else {

				// *toOne
				val opposite = prop.resolvedOpposite

				// When we have no opposite, then the master-side has no collection
				// and we assume a many-to-one relation.
				// A one-to-one relation needs an "opposite" on both sides.
				if (opposite != null && !opposite.toMany) {

					// @OneToOne
					addOneToOneAnno(prop, jvmField)
				} else {

					// @ManyToOne
					addManyToOneAnno(prop, jvmField)
				}
			}

			if (prop.resultFilters !== null) {
				prop.resultFilters.addConstraintsAnno(jvmField)
			}

		} else {

			// it is a bean and needs @embedded annotations
			jvmField.annotations += prop.toAnnotation(typeof(Basic))
			addAnno(prop, jvmField, prop.toAnnotation(typeof(Embedded)))
			if (prop.toMany) {
				addAnno(prop, jvmField, prop.toAnnotation(typeof(ElementCollection)))
			}
		}

		// create the properties annotations
		prop.toPropertiesAnnotation(mergeKeyAndValues(prop), jvmField)

		toConstraintAnnotations(prop, jvmField)
	}

	def private addOneToManyAnno(LReference prop, JvmAnnotationTarget jvmAnnTarget) {

		val col = prop.toAnnotation(typeof(JoinColumn))
		col.addAnnAttr(prop, "name", prop.toColumnName)
		if (prop.bounds.required) {
			col.addAnnAttr(prop, "nullable", false)
		}
		addAnno(prop, jvmAnnTarget, col)

		val ann = prop.toAnnotation(typeof(OneToMany))
		if (prop.opposite != null) {
			if (prop.opposite.name == null) {
				ann.addAnnAttr(prop, "mappedBy", "")
			} else {
				ann.addAnnAttr(prop, "mappedBy", prop.opposite.name)
			}
		}

		// ATTENTION - never ever touch cascading. Jörg und Flo
		//
		val cascaded = <CascadeType>newArrayList
		if (prop.cascadeRemove) {
			cascaded.add(CascadeType::REMOVE)
			if(prop.cascadeMergePersist) {
				cascaded.add(CascadeType::MERGE)
				cascaded.add(CascadeType::PERSIST)
			}
			ann.addAnnAttr(prop, "cascade", cascaded.toArray(<Enum>newArrayOfSize(cascaded.length)))
			ann.addAnnAttr(prop, "orphanRemoval", true)
			ann.addAnnAttr(prop, "fetch", FetchType::EAGER)
		} else if(prop.cascadeMergePersist) {
			cascaded.add(CascadeType::MERGE)
			cascaded.add(CascadeType::PERSIST)
			ann.addAnnAttr(prop, "cascade", cascaded.toArray(<Enum>newArrayOfSize(cascaded.length)))
			ann.addAnnAttr(prop, "orphanRemoval", false)
			ann.addAnnAttr(prop, "fetch", FetchType::LAZY)
		}
		addAnno(prop, jvmAnnTarget, ann)
//		this leads to unwanted selects during merge
//		addAnno(prop, jvmAnnTarget, prop.toAnnotation(typeof(Noncacheable)))

		if (prop.isGrouped) {
			val groupAnnotation = prop.toAnnotation(typeof(UIGroup))
			groupAnnotation.addAnnAttr(prop, "name", prop.groupName)
			addAnno(prop, jvmAnnTarget, groupAnnotation)
		}
		if (prop.asGrid) {
			addAnno(prop, jvmAnnTarget, prop.toAnnotation(typeof(AsGrid)))
		}
		if (prop.asTable) {
			addAnno(prop, jvmAnnTarget, prop.toAnnotation(typeof(AsTable)))
		}
	}

	def private addManyToManyAnno(LReference prop, JvmAnnotationTarget jvmAnnTarget) {
		// throw new UnsupportedOperationException("ManyToMany not yet supported");
	}

	def private addManyToOneAnno(LReference prop, JvmAnnotationTarget jvmAnnTarget) {
		val manyToOne = prop.toAnnotation(typeof(ManyToOne))
		if (prop.bounds.required) {
			manyToOne.addAnnAttr(prop, "optional", !prop.bounds.required)
		}
		manyToOne.addAnnAttr(prop, "fetch", FetchType::LAZY)
		val opposite = prop.resolvedOpposite

		addAnno(prop, jvmAnnTarget, manyToOne)

		val joinColumn = prop.toAnnotation(typeof(JoinColumn))
		joinColumn.addAnnAttr(prop, "name", prop.toColumnName)
		if (prop.bounds.required) {
			joinColumn.addAnnAttr(prop, "nullable", false)
		}
		addAnno(prop, jvmAnnTarget, joinColumn)
		if (prop.sideKick) {
			addAnno(prop, jvmAnnTarget, prop.toAnnotation(typeof(SideKick)))
		}
	}

	def private addOneToOneAnno(LReference prop, JvmAnnotationTarget jvmAnnTarget) {
		val oneToOne = prop.toAnnotation(typeof(OneToOne))
		if (prop.bounds.required) {
			oneToOne.addAnnAttr(prop, "optional", !prop.bounds.required)
		}
		val opposite = prop.resolvedOpposite
		if (opposite != null && (prop.cascadeMergePersist || prop.cascadeRemove)) {
			oneToOne.addAnnAttr(prop, "mappedBy", if(opposite.name != null) opposite.name else "")
		}
		val cascaded = <CascadeType>newArrayList
		if (prop.cascadeRemove) {
			cascaded.add(CascadeType::REMOVE)
			if(prop.cascadeMergePersist) {
				cascaded.add(CascadeType::MERGE)
				cascaded.add(CascadeType::PERSIST)
			}
			oneToOne.addAnnAttr(prop, "cascade", cascaded.toArray(<Enum>newArrayOfSize(cascaded.length)))
			oneToOne.addAnnAttr(prop, "orphanRemoval", true)
			oneToOne.addAnnAttr(prop, "fetch", FetchType::EAGER)
		} else if(prop.cascadeMergePersist) {
			cascaded.add(CascadeType::MERGE)
			cascaded.add(CascadeType::PERSIST)
			oneToOne.addAnnAttr(prop, "cascade", cascaded.toArray(<Enum>newArrayOfSize(cascaded.length)))
			oneToOne.addAnnAttr(prop, "orphanRemoval", false)
			oneToOne.addAnnAttr(prop, "fetch", FetchType::LAZY)
		}
		addAnno(prop, jvmAnnTarget, oneToOne)

		if (opposite != null && opposite.cascading) {
			val joinColumn = prop.toAnnotation(typeof(JoinColumn))
			joinColumn.addAnnAttr(prop, "name", prop.toColumnName)
			if (prop.bounds.required) {
				joinColumn.addAnnAttr(prop, "nullable", false)
			}
			addAnno(prop, jvmAnnTarget, joinColumn)
		}
		if (prop.sideKick) {
			addAnno(prop, jvmAnnTarget, prop.toAnnotation(typeof(SideKick)))
		}
	}

	def void addConstraintsAnno(LResultFilters constraints, JvmField jvmField) {

		// process the LAttributeMatchingConstraint
		if (!constraints.resultFilters.filter[it instanceof LAttributeMatchingConstraint].empty) {

			// collect all inner annotations
			val innerAnnotations = newArrayList()
			constraints.resultFilters.filter[it instanceof LAttributeMatchingConstraint].map [
				it as LAttributeMatchingConstraint
			].forEach [
				val innerAnno = constraints.toAnnotation(typeof(TargetEnumConstraint))
				innerAnno.addAnnAttr(it, "targetProperty", attribute.name)
				innerAnno.addAnnAttr(it, "enumClass", attribute.toTypeReference)
				innerAnno.addAnnAttr(it, "enumLiteral", matchingLiteral.name)
				innerAnnotations += innerAnno
			]

			// now create the outer annotation and add the array of inner annotations
			val mainAnno = constraints.toAnnotation(typeof(TargetEnumConstraints))
			mainAnno.addAnnAttr(constraints, "constraints",
				innerAnnotations.toArray(<JvmAnnotationReference>newArrayOfSize(innerAnnotations.length)))
			jvmField.annotations += mainAnno
		}
	}

	def dispatch addDisposeFieldAnnotation(LEntity entity, JvmField field) {
		val anno = entity.toAnnotation(typeof(Transient))
		addAnno(entity, field, anno)

		addAnno(entity, field, entity.toAnnotation(typeof(Dispose)))
	}

	def dispatch addDisposeFieldAnnotation(LBean entity, JvmField field) {
		val anno = entity.toAnnotation(typeof(Transient))
		addAnno(entity, field, anno)

		addAnno(entity, field, entity.toAnnotation(typeof(Dispose)))
	}

	def dispatch addDisposeFieldAnnotation(LEntity entity, JvmOperation op) {
		addAnno(entity, op, entity.toAnnotation(typeof(Dispose)))
	}

	def dispatch addDisposeFieldAnnotation(LBean entity, JvmOperation op) {
		addAnno(entity, op, entity.toAnnotation(typeof(Dispose)))
	}

	def dispatch boolean isValidAllowed(LBean type) {
		return true;
	}
	
	/**
	 * @noreference This method is called by the framework
	 * @nooverride
	 */
	def void setContext(Resource resource) {
//		_annotationTypesBuilder = annotationRefBuilderFactory.create(resource.getResourceSet());
//		_typeReferenceBuilder = typeRefBuilderFactory.create(resource.getResourceSet());
		println
	}
	

}
