| /** |
| * 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.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.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.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.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.TargetEnumConstraint |
| import org.eclipse.osbp.runtime.common.annotations.TargetEnumConstraints |
| 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.xbase.jvmmodel.JvmTypesBuilder |
| import org.eclipse.persistence.annotations.Noncacheable |
| |
| /** |
| * 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 |
| |
| def protected dispatch void internalProcessAnnotation(LBean bean, JvmGenericType jvmType) { |
| bean.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(jvmType); |
| |
| bean.addAnno(jvmType, bean.toAnnotation(typeof(Embeddable))) |
| } |
| |
| def protected dispatch void internalProcessAnnotation(LOperation member, JvmField jvmOperation) { |
| member.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(jvmOperation); |
| } |
| |
| def protected dispatch void internalProcessAnnotation(LEntity entity, JvmGenericType jvmType) { |
| entity.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(jvmType); |
| if (entity.mappedSuperclass) { |
| addAnno(entity, jvmType, entity.toAnnotation(typeof(MappedSuperclass))) |
| } else { |
| |
| // @Entity |
| addAnno(entity, jvmType, entity.toAnnotation(typeof(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", 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(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) { |
| prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(jvmField); |
| |
| 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) { |
| prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(jvmField); |
| |
| if (prop.id) { |
| jvmField.annotations += prop.toAnnotation(typeof(Id)) |
| jvmField.annotations += prop.toAnnotation(typeof(GeneratedValue)) |
| } else if (prop.uuid) { |
| jvmField.annotations += prop.toAnnotation(typeof(Id)) |
| } else if (prop.version) { |
| jvmField.annotations += prop.toAnnotation(typeof(Version)) |
| } else if (prop.transient) { |
| addAnno(prop, jvmField, prop.toAnnotation(typeof(Transient))) |
| } else { |
| 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))) |
| |
| jvmField.toAttributesOverride(prop) |
| } |
| |
| if (prop.domainKey) { |
| addAnno(prop, jvmField, prop.toAnnotation(typeof(DomainKey))) |
| } |
| |
| if (prop.domainDescription) { |
| addAnno(prop, jvmField, prop.toAnnotation(typeof(DomainDescription))) |
| } |
| } |
| |
| 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) |
| } |
| } |
| } |
| |
| // 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) { |
| prop.resolvedAnnotations.filter([! exclude]).map([annotation]).translateAnnotationsTo(jvmField); |
| |
| 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; |
| } |
| } |
| |
| 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.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.toValidAnnotation(jvmField) |
| } |
| |
| for (c : prop.constraints) { |
| c.toConstraintAnnotation(jvmField) |
| } |
| } |
| |
| def protected dispatch void internalProcessAnnotation(LBeanReference prop, JvmField jvmField) { |
| prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(jvmField); |
| |
| 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) |
| } |
| } |
| if (prop.cascading) { |
| ann.addAnnAttr(prop, "cascade", CascadeType::ALL) |
| ann.addAnnAttr(prop, "orphanRemoval", true) |
| } else { |
| // val cascaded = newArrayList(CascadeType::DETACH, CascadeType::MERGE, CascadeType::PERSIST, |
| // CascadeType::REFRESH) |
| // |
| // ann.addAnnAttr(prop, "cascade", cascaded.toArray(<Enum> newArrayOfSize(cascaded.length))) |
| // ann.addAnnAttr(prop, "orphanRemoval", false) |
| } |
| addAnno(prop, jvmAnnTarget, ann) |
| |
| addAnno(prop, jvmAnnTarget, prop.toAnnotation(typeof(Noncacheable))) |
| } |
| |
| 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 |
| if (opposite != null && opposite.cascading) { |
| val cascaded = newArrayList(CascadeType::DETACH, CascadeType::MERGE, CascadeType::PERSIST, |
| CascadeType::REFRESH) |
| manyToOne.addAnnAttr(prop, "cascade", cascaded.toArray(<Enum> newArrayOfSize(cascaded.length))) |
| } |
| 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) |
| } |
| |
| 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.cascading) { |
| oneToOne.addAnnAttr(prop, "mappedBy", if(opposite.name != null) opposite.name else "") |
| } |
| if (prop.cascading) { |
| oneToOne.addAnnAttr(prop, "cascade", CascadeType::ALL) |
| oneToOne.addAnnAttr(prop, "orphanRemoval", true) |
| } |
| |
| //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) |
| } |
| } |
| |
| 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.typeJvm.cloneWithProxies) |
| 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; |
| } |
| |
| } |