| /** |
| * 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.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.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.CreateAt |
| import org.eclipse.osbp.runtime.common.annotations.CreateBy |
| 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.Hidden |
| import org.eclipse.osbp.runtime.common.annotations.HistIsCurrent |
| import org.eclipse.osbp.runtime.common.annotations.HistIsCustomVersion |
| import org.eclipse.osbp.runtime.common.annotations.HistValidUntil |
| import org.eclipse.osbp.runtime.common.annotations.HistorizedObject |
| 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.ReadOnly |
| import org.eclipse.osbp.runtime.common.annotations.SideKick |
| import org.eclipse.osbp.runtime.common.annotations.TargetEnumConstraint |
| import org.eclipse.osbp.runtime.common.annotations.TargetEnumConstraints |
| import org.eclipse.osbp.runtime.common.annotations.TimedependentObject |
| import org.eclipse.osbp.runtime.common.annotations.UIGroup |
| import org.eclipse.osbp.runtime.common.annotations.UniqueEntry |
| import org.eclipse.osbp.runtime.common.annotations.UpdateAt |
| import org.eclipse.osbp.runtime.common.annotations.UpdateBy |
| 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.JvmType |
| import org.eclipse.xtext.common.types.JvmTypeReference |
| import org.eclipse.xtext.common.types.util.TypeReferences |
| import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder |
| import org.eclipse.osbp.runtime.common.annotations.ExtraStyle |
| |
| /** |
| * 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 |
| @Inject |
| private TypeReferences references; |
| |
| def protected dispatch void internalProcessAnnotation(LDto dto, JvmGenericType jvmType) { |
| dto.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(jvmType); |
| |
| if (dto.historized) { |
| addAnno(dto, jvmType, dto.toAnnotation(typeof(HistorizedObject))) |
| } else if (dto.timedependent) { |
| addAnno(dto, jvmType, dto.toAnnotation(typeof(TimedependentObject))) |
| } |
| |
| } |
| |
| 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)) |
| } |
| |
| if (prop.attributeHidden) { |
| field.annotations += prop.toAnnotation(typeof(Hidden)) |
| } |
| |
| if (prop.attributeReadOnly) { |
| field.annotations += prop.toAnnotation(typeof(ReadOnly)) |
| } |
| |
| if (prop.extraStyle !== null) { |
| val styleAnnotation = prop.toAnnotation(typeof(ExtraStyle)) |
| styleAnnotation.addAnnAttr(prop, "name", prop.extraStyle) |
| field.annotations += styleAnnotation |
| } |
| |
| // 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)) |
| } |
| |
| if (prop.inheritedFeature.attributeHidden) { |
| field.annotations += prop.toAnnotation(typeof(Hidden)) |
| } |
| |
| if (prop.inheritedFeature.attributeReadOnly) { |
| field.annotations += prop.toAnnotation(typeof(ReadOnly)) |
| } |
| |
| if (prop.inheritedFeature.extraStyle !== null) { |
| val styleAnnotation = prop.toAnnotation(typeof(ExtraStyle)) |
| styleAnnotation.addAnnAttr(prop, "name", prop.inheritedFeature.extraStyle) |
| field.annotations += styleAnnotation |
| } |
| |
| // create the properties annotations |
| prop.toPropertiesAnnotation(mergeKeyAndValues(prop), field) |
| |
| if (prop.inheritedFeature.type.validAllowed) { |
| prop.toValidAnnotation(field) |
| } |
| |
| if (prop.inheritedFeature.type instanceof LBean && (prop.inheritedFeature.type as LBean).beanOnTab) { |
| prop.toBeanOnTabAnnotation(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.entity.historized || att.entity.timedependent) { |
| if (att.isHistorizedValidUntilAnnotation) { |
| field.annotations += prop.toAnnotation(typeof(HistValidUntil)) |
| } |
| if (att.isHistorizedIsCurrentAnnotation) { |
| field.annotations += prop.toAnnotation(typeof(HistIsCurrent)) |
| } |
| if (att.isHistorizedIsCustomVersionAnnotation) { |
| field.annotations += prop.toAnnotation(typeof(HistIsCustomVersion)) |
| } |
| } |
| |
| 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)) |
| } |
| |
| if (att.annotationPresent(references.findDeclaredType(typeof(UpdateBy), att))) { |
| field.annotations += prop.toAnnotation(typeof(UpdateBy)) |
| } |
| |
| if (att.annotationPresent(references.findDeclaredType(typeof(UpdateAt), att))) { |
| field.annotations += prop.toAnnotation(typeof(UpdateAt)) |
| } |
| |
| if (att.annotationPresent(references.findDeclaredType(typeof(CreateBy), att))) { |
| field.annotations += prop.toAnnotation(typeof(CreateBy)) |
| } |
| |
| if (att.annotationPresent(references.findDeclaredType(typeof(CreateAt), att))) { |
| field.annotations += prop.toAnnotation(typeof(CreateAt)) |
| } |
| |
| if (att.isGrouped) { |
| val groupAnnotation = prop.toAnnotation(typeof(UIGroup)) |
| groupAnnotation.addAnnAttr(prop, "name", att.groupName) |
| field.annotations += groupAnnotation |
| } |
| } |
| |
| // also inherit annotations from the entities |
| prop.inheritedFeature.toInheritedConstraintAnnotations(field) |
| } |
| |
| def boolean annotationPresent(LEntityAttribute attribute, JvmType type) { |
| for (anno : attribute.resolvedAnnotations) { |
| if (anno.annotation.annotationType === type) { |
| return true |
| } |
| } |
| return false |
| } |
| |
| 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) |
| } |
| |
| if (inheritedRef.isGrouped) { |
| val groupAnnotation = prop.toAnnotation(typeof(UIGroup)) |
| groupAnnotation.addAnnAttr(prop, "name", inheritedRef.groupName) |
| field.annotations += groupAnnotation |
| } |
| if (inheritedRef.asGrid) { |
| field.annotations += prop.toAnnotation(typeof(AsGrid)) |
| } |
| if (inheritedRef.asTable) { |
| field.annotations += prop.toAnnotation(typeof(AsTable)) |
| } |
| if (inheritedRef.sideKick) { |
| field.annotations += prop.toAnnotation(typeof(SideKick)) |
| } |
| if (inheritedRef.referenceHidden) { |
| field.annotations += prop.toAnnotation(typeof(Hidden)) |
| } |
| |
| if (inheritedRef.referenceReadOnly) { |
| field.annotations += prop.toAnnotation(typeof(ReadOnly)) |
| } |
| |
| } |
| |
| 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) |
| } |
| } |
| } |