blob: 2c2f882769126c58cd1575d77c4a0ecd8cefacd6 [file] [log] [blame]
/**
* 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 v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Florian Pirchner - Initial implementation
*/
package org.eclipse.osbp.dsl.dto.xtext.jvmmodel
import com.google.inject.Inject
import java.util.List
import org.eclipse.osbp.dsl.dto.xtext.extensions.AnnotationExtension
import org.eclipse.osbp.dsl.dto.xtext.extensions.DtoModelExtensions
import org.eclipse.osbp.dsl.semantic.common.types.LAttributeMatchingConstraint
import org.eclipse.osbp.dsl.semantic.common.types.LKeyAndValue
import org.eclipse.osbp.dsl.semantic.common.types.LResultFilters
import org.eclipse.osbp.dsl.semantic.dto.LDto
import org.eclipse.osbp.dsl.semantic.dto.LDtoAbstractAttribute
import org.eclipse.osbp.dsl.semantic.dto.LDtoAttribute
import org.eclipse.osbp.dsl.semantic.dto.LDtoInheritedAttribute
import org.eclipse.osbp.dsl.semantic.dto.LDtoInheritedReference
import org.eclipse.osbp.dsl.semantic.dto.LDtoReference
import org.eclipse.osbp.dsl.semantic.entity.LBean
import org.eclipse.osbp.dsl.semantic.entity.LBeanAttribute
import org.eclipse.osbp.dsl.semantic.entity.LBeanReference
import org.eclipse.osbp.dsl.semantic.entity.LEntityAttribute
import org.eclipse.osbp.dsl.semantic.entity.LEntityReference
import org.eclipse.osbp.runtime.common.annotations.AsKanbanOrdering
import org.eclipse.osbp.runtime.common.annotations.AsKanbanState
import org.eclipse.osbp.runtime.common.annotations.Dirty
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.DomainReference
import org.eclipse.osbp.runtime.common.annotations.Filter
import org.eclipse.osbp.runtime.common.annotations.FilterDepth
import org.eclipse.osbp.runtime.common.annotations.Id
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.UniqueEntry
import org.eclipse.osbp.runtime.common.annotations.Version
import org.eclipse.xtext.common.types.JvmAnnotationReference
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.JvmTypeReference
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
/**
* 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 JvmTypesBuilder
@Inject extension TypeHelper
@Inject extension DtoModelExtensions
@Inject extension AnnotationExtension
def protected dispatch void internalProcessAnnotation(LDto dto, JvmGenericType jvmType) {
dto.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(jvmType);
}
def protected dispatch void internalProcessAnnotation(LDtoReference prop, JvmGenericType jvmType) {
prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(jvmType);
}
def protected dispatch void internalProcessAnnotation(LDtoReference prop, JvmField field) {
prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(field);
field.annotations += prop.toAnnotation(typeof(DomainReference))
if (prop.cascading) {
prop.toValidAnnotation(field)
}
// create the properties annotations
prop.toPropertiesAnnotation(mergeKeyAndValues(prop), field)
}
def protected List<LKeyAndValue> mergeKeyAndValues(LDtoInheritedAttribute att) {
val keyAndValues = newArrayList()
// add all datatype properties to the list
att.inheritedFeature.addDatatypeKeyAndValues(keyAndValues)
// add the attribute properties
keyAndValues.addAll(att.inheritedFeature.properties)
// add the attribute properties
keyAndValues.addAll(att.properties)
// remove duplicate keys
keyAndValues.removeDuplicateKeys
return keyAndValues
}
def protected List<LKeyAndValue> mergeKeyAndValues(LDtoInheritedReference ref) {
val keyAndValues = newArrayList()
// add the attribute properties
keyAndValues.addAll(ref.inheritedFeature.properties)
// add the attribute properties
keyAndValues.addAll(ref.properties)
// remove duplicate keys
keyAndValues.removeDuplicateKeys
return keyAndValues
}
def protected dispatch void internalProcessAnnotation(LDtoAttribute prop, JvmField field) {
prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(field);
if (prop.id || prop.uuid) {
field.annotations += prop.toAnnotation(typeof(Id))
}
if (prop.version) {
field.annotations += prop.toAnnotation(typeof(Version))
}
if (prop.domainKey) {
field.annotations += prop.toAnnotation(typeof(DomainKey))
}
if (prop.domainDescription) {
field.annotations += prop.toAnnotation(typeof(DomainDescription))
}
if (prop.dirty) {
field.annotations += prop.toAnnotation(typeof(Dirty))
}
// create the properties annotations
prop.toPropertiesAnnotation(mergeKeyAndValues(prop), field)
if (prop.type.validAllowed) {
prop.toValidAnnotation(field)
}
super.toDatatypeBasedConstraintAnnotations(prop, field)
}
def protected dispatch void internalProcessAnnotation(LDtoInheritedAttribute prop, JvmField field) {
prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(field);
if (prop.inheritedFeature.id || prop.inheritedFeature.uuid) {
field.annotations += prop.toAnnotation(typeof(Id))
}
if (prop.inheritedFeature.version) {
field.annotations += prop.toAnnotation(typeof(Version))
}
if (prop.inheritedFeature.domainKey) {
field.annotations += prop.toAnnotation(typeof(DomainKey))
}
if (prop.inheritedFeature.domainDescription) {
field.annotations += prop.toAnnotation(typeof(DomainDescription))
}
// create the properties annotations
prop.toPropertiesAnnotation(mergeKeyAndValues(prop), field)
if (prop.inheritedFeature.type.validAllowed) {
prop.toValidAnnotation(field)
}
// add the range and filter annotation
if (prop.inheritedFeature.isFiltering) {
field.annotations += prop.toAnnotation(typeof(Filter))
}
if (prop.inheritedFeature.isRangeFiltering) {
field.annotations += prop.toAnnotation(typeof(Range))
}
if (prop.inheritedFeature.isUniqueEntry) {
field.annotations += prop.toAnnotation(typeof(UniqueEntry))
}
if (prop.inheritedFeature instanceof LEntityAttribute) {
val att = prop.inheritedFeature as LEntityAttribute
if (att.isOnKanbanCard) {
field.annotations += prop.toAnnotation(typeof(OnKanbanCard))
}
if (att.isAsKanbanOrdering) {
field.annotations += prop.toAnnotation(typeof(AsKanbanOrdering))
}
if (att.asKanbanState) {
field.annotations += prop.toAnnotation(typeof(AsKanbanState))
}
}
// also inherit annotations from the entities
prop.inheritedFeature.toInheritedConstraintAnnotations(field)
}
def protected dispatch void internalProcessAnnotation(LDtoInheritedReference prop, JvmField field) {
prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(field);
field.annotations += prop.toAnnotation(typeof(DomainReference))
val inheritedRef = prop.inheritedFeature
if (inheritedRef instanceof LEntityReference) {
if (inheritedRef.resultFilters != null) {
inheritedRef.resultFilters.addConstraintsAnno(field, prop.type)
}
if (inheritedRef.cascading) {
prop.toValidAnnotation(field)
}
// also inherit annotations from the entities
inheritedRef.toInheritedConstraintAnnotations(field)
// create the properties annotations
prop.toPropertiesAnnotation(mergeKeyAndValues(prop), field)
if (inheritedRef.filterDepth >= 0) {
val anno = inheritedRef.toAnnotation(typeof(FilterDepth))
anno.addAnnAttr(inheritedRef, "depth", inheritedRef.filterDepth)
field.annotations += anno
}
} else if (inheritedRef instanceof LBeanReference) {
if (inheritedRef.resultFilters != null) {
inheritedRef.resultFilters.addConstraintsAnno(field, prop.type)
}
if (inheritedRef.cascading) {
prop.toValidAnnotation(field)
}
// also inherit annotations from the entities
inheritedRef.toInheritedConstraintAnnotations(field)
// create the properties annotations
prop.toPropertiesAnnotation(mergeKeyAndValues(prop), field)
}
}
def void addConstraintsAnno(LResultFilters constraints, JvmField jvmField, LDto mapsTo) {
// 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 enumClassTypeRef = attribute.name.findReplacementEnum(mapsTo)
if (enumClassTypeRef != null) {
val innerAnno = constraints.toAnnotation(typeof(TargetEnumConstraint))
innerAnno.addAnnAttr(it, "targetProperty", attribute.name)
innerAnno.addAnnAttr(it, "enumClass", enumClassTypeRef)
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
}
}
/**
* Iterates all attributes of the target dto. If a matching att name was found, the jvmType proxy will be returned.
*/
def JvmTypeReference findReplacementEnum(String property, LDto mapsTo) {
for (att : mapsTo.allFeatures.filter[it instanceof LDtoAbstractAttribute].map[it as LDtoAbstractAttribute]) {
if (att instanceof LDtoInheritedAttribute) {
if (att.inheritedFeature?.name.equals(property)) {
return att.toDtoTypeReference
}
} else {
if (att.name.equals(property)) {
return att.toDtoTypeReference
}
}
}
return null
}
def dispatch addDisposeFieldAnnotation(LDto dto, JvmField field) {
addAnno(dto, field, dto.toAnnotation(typeof(Dispose)))
}
def dispatch addDisposeFieldAnnotation(LDto dto, JvmOperation op) {
addAnno(dto, op, dto.toAnnotation(typeof(Dispose)))
}
def dispatch boolean isValidAllowed(LBean type) {
return true;
}
def dispatch void toInheritedConstraintAnnotations(LDtoInheritedAttribute prop, JvmField jvmField) {
val feature = prop.inheritedFeature
if (feature instanceof LBeanAttribute) {
feature.toInheritedConstraintAnnotations(jvmField)
} else if (feature instanceof LEntityAttribute) {
feature.toInheritedConstraintAnnotations(jvmField)
}
}
def dispatch void toInheritedConstraintAnnotations(LBeanAttribute prop, JvmField jvmField) {
for (c : prop.constraints) {
c.toConstraintAnnotation(jvmField)
}
if (prop.constraints.empty) {
super.toDatatypeBasedConstraintAnnotations(prop, jvmField)
}
}
def dispatch void toInheritedConstraintAnnotations(LBeanReference prop, JvmField jvmField) {
for (c : prop.constraints) {
c.toConstraintAnnotation(jvmField)
}
}
def dispatch void toInheritedConstraintAnnotations(LEntityAttribute prop, JvmField jvmField) {
for (c : prop.constraints) {
c.toConstraintAnnotation(jvmField)
}
if (prop.constraints.empty) {
super.toDatatypeBasedConstraintAnnotations(prop, jvmField)
}
}
def dispatch void toInheritedConstraintAnnotations(LEntityReference prop, JvmField jvmField) {
for (c : prop.constraints) {
c.toConstraintAnnotation(jvmField)
}
}
}