blob: c8f63a7c605ff4a2e695826ef097344c72cd6217 [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.extensions
import com.google.inject.Inject
import java.util.List
import org.eclipse.emf.ecore.EObject
import org.eclipse.osbp.dsl.common.xtext.extensions.ModelExtensions
import org.eclipse.osbp.dsl.entity.xtext.extensions.Constants
import org.eclipse.osbp.dsl.semantic.common.helper.Bounds
import org.eclipse.osbp.dsl.semantic.common.types.LAttribute
import org.eclipse.osbp.dsl.semantic.common.types.LDataType
import org.eclipse.osbp.dsl.semantic.common.types.LEnum
import org.eclipse.osbp.dsl.semantic.common.types.LFeature
import org.eclipse.osbp.dsl.semantic.common.types.LReference
import org.eclipse.osbp.dsl.semantic.common.types.LType
import org.eclipse.osbp.dsl.semantic.dto.LDto
import org.eclipse.osbp.dsl.semantic.dto.LDtoAbstractAttribute
import org.eclipse.osbp.dsl.semantic.dto.LDtoAbstractReference
import org.eclipse.osbp.dsl.semantic.dto.LDtoAttribute
import org.eclipse.osbp.dsl.semantic.dto.LDtoFeature
import org.eclipse.osbp.dsl.semantic.dto.LDtoInheritedAttribute
import org.eclipse.osbp.dsl.semantic.dto.LDtoInheritedReference
import org.eclipse.osbp.dsl.semantic.dto.LDtoOperation
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.LEntity
import org.eclipse.osbp.dsl.semantic.entity.LEntityAttribute
import org.eclipse.osbp.dsl.semantic.entity.LEntityReference
import org.eclipse.xtext.common.types.JvmTypeReference
import org.eclipse.xtext.common.types.TypesFactory
import org.eclipse.xtext.common.types.util.TypeReferences
import org.eclipse.xtext.naming.IQualifiedNameProvider
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
class DtoModelExtensions extends ModelExtensions {
@Inject extension IQualifiedNameProvider
@Inject extension JvmTypesBuilder
@Inject extension MethodNamingExtensions
@Inject TypeReferences references;
/**
* Creates a type reference with respect to mappings to DTOs. For instance "Item"-Entity is mapped to ItemDTO
*/
def dispatch JvmTypeReference toDtoTypeReference(LDtoAbstractReference prop) {
return prop.type.toTypeReference
}
/**
* Creates a type reference with respect to mappings to DTOs. For instance "Item"-Entity is mapped to ItemDTO
*/
def dispatch JvmTypeReference toDtoTypeReference(LDtoAbstractAttribute prop) {
return prop.toDataTypeTypeReference
}
override JvmTypeReference toSyntheticTypeReference(LDataType type) {
switch (type.syntheticSelector) {
case Constants::DT_INTERNAL_IS_CURRENT_VERSION:
references.findDeclaredType(Boolean::TYPE, type).newTypeRef()
case Constants::DT_INTERNAL_OBJECT_VERSION:
references.findDeclaredType(Integer::TYPE, type).newTypeRef()
case Constants::DT_INTERNAL_OBJECT_ID:
if (type.syntheticType !== null) {
for (att : (type.syntheticType as LEntity).allAttributes) {
if (att.id || att.uuid) {
return att.toTypeReference
}
}
}
}
}
/**
* Creates a type reference with respect to mappings to DTOs. For instance "Item"-Entity is mapped to ItemDTO
*/
def dispatch JvmTypeReference toDtoTypeReference(LEntityAttribute prop, LDtoInheritedAttribute dtoAtt) {
if(prop.type instanceof LEnum) {
val LEnum type = prop.type as LEnum
val fqn = type.toDTOEnumFullyQualifiedName.toString
return references.getTypeForName(fqn, type, null)
} else if (prop.type instanceof LBean || prop.type instanceof LEntity) {
return dtoAtt.inheritedFeature.toTypeReference
} else {
return super.toTypeReference(prop)
}
}
def dispatch JvmTypeReference toDtoTypeReference(LDtoInheritedAttribute prop, LDtoInheritedAttribute dtoAtt) {
return null
}
/**
* Creates a type reference with respect to mappings to DTOs. For instance "Item"-Entity is mapped to ItemDTO
*/
def dispatch JvmTypeReference toDtoTypeReference(LBeanAttribute prop, LDtoInheritedAttribute dtoAtt) {
if(prop.type instanceof LEnum) {
val LEnum type = prop.type as LEnum
val fqn = type.toDTOEnumFullyQualifiedName.toString
return references.getTypeForName(fqn, type, null)
} else if (prop.type instanceof LBean || prop.type instanceof LEntity) {
return dtoAtt.inheritedFeature.toTypeReference
} else {
return super.toTypeReference(prop)
}
}
/**
* Creates a type reference with respect to mappings to DTOs. For instance "Item"-Entity is mapped to ItemDTO
*/
def dispatch JvmTypeReference toDtoTypeReference(LEntityReference prop, LDtoInheritedReference dtoRef) {
return dtoRef.inheritedFeature.toTypeReference
}
/**
* Creates a type reference with respect to mappings to DTOs. For instance "Item"-Entity is mapped to ItemDTO
*/
def dispatch JvmTypeReference toDtoTypeReference(LBeanReference prop, LDtoInheritedAttribute dtoRef) {
return dtoRef.inheritedFeature.toTypeReference
}
/**
* Creates a type reference with respect to mappings to DTOs. For instance "Item"-Entity is mapped to ItemDTO
*/
def dispatch JvmTypeReference toDtoTypeReference(LDtoInheritedAttribute prop) {
if (prop.type !== null) {
// if the type is a different one, then use the type of the property
// it needs to be mapped by a custom mapper in dsl
return prop.type.toTypeReference
}
// creates a proxy reference
return prop.inheritedFeature?.toDtoTypeReference(prop).cloneWithProxies
}
/**
* Creates a type reference with respect to mappings to DTOs. For instance "Item"-Entity is mapped to ItemDTO
*/
def dispatch JvmTypeReference toDtoTypeReference(LDtoInheritedReference prop) {
if (prop.type !== null) {
return prop.type.toTypeReference
}
// creates a proxy reference
return prop.inheritedFeature?.toDtoTypeReference(prop).cloneWithProxies
}
/**
* Creates a type reference with respect to mappings to DTOs. For instance "Item"-Entity is mapped to ItemDTO
*/
def JvmTypeReference toDtoTypeReferenceWithMultiplicity(LDtoFeature prop) {
var ref = prop.toDtoTypeReference
if (ref !== null && prop.bounds.toMany) {
ref = references.getTypeForName(typeof(List), prop, ref)
}
return ref
}
/**
* Creates a type reference with respect to multiplicity
*/
def JvmTypeReference toRawTypeReferenceWithMultiplicity(LDtoFeature prop) {
var ref = prop.toRawTypeRefernce;
if (prop.bounds.toMany) {
ref = references.getTypeForName(typeof(List), prop, ref)
}
return ref
}
def dispatch isCascading(LDtoOperation prop) {
false
}
def LDtoAbstractReference getResolvedOpposite(LDtoReference prop) {
// For a toMany that has already an opposite, return it.
// Otherwise search in the referenced type for the property with the owner type.
if (prop.opposite !== null) {
return prop.opposite
} else if (prop.type instanceof LDto) {
val LDto ref = prop.type as LDto
ref.references.findFirst[it.opposite === prop]
}
}
/**
* Returns true, if toCheck can be cast to superType
*/
def boolean isCastable(LDto toCheck, LDto superType) {
val String toCheckFqn = toCheck.fullyQualifiedName.toString
val String superTypeFqn = superType.fullyQualifiedName.toString
if (toCheckFqn.equals(superTypeFqn)) {
return true
} else {
val LDto toCheckSuperType = toCheck.getSuperType
if (toCheckSuperType !== null) {
return toCheckSuperType.isCastable(superType)
} else {
return false;
}
}
}
def dispatch inherited(LFeature prop) {
return false
}
def dispatch inherited(LDtoInheritedReference prop) {
return true
}
def dispatch inherited(LDtoInheritedAttribute prop) {
return true
}
def dispatch boolean derived(LDtoInheritedReference prop) {
return false
}
def dispatch boolean derived(LDtoInheritedAttribute prop) {
return if(prop.inheritedFeature != null) prop.inheritedFeature.derived else false
}
/**
* The binary <code>+</code> operator that concatenates two strings.
*
* @param a
* a string.
* @param b
* another string.
* @return <code>a + b</code>
*/
def static String operator_plus(String a, String b) {
if (a === null || b === null)
return ""
return a + b;
}
def dispatch String toTypeName(LDtoAttribute prop) {
prop.type.name
}
def dispatch String toTypeName(LDtoInheritedAttribute prop) {
if (prop.type !== null) {
prop.type.name
} else {
prop.inheritedFeature.^type.name
}
}
def dispatch String toTypeName(LDtoReference prop) {
prop.type?.name
}
def dispatch String toTypeName(LDtoInheritedReference prop) {
prop.type?.name
}
def dispatch String toQualifiedTypeName(LType type) {
type.fullyQualifiedName.toString
}
def dispatch String toQualifiedTypeName(LDtoAttribute prop) {
prop.type.fullyQualifiedName.toString
}
def dispatch String toQualifiedTypeName(LDtoInheritedAttribute prop) {
if (prop.type !== null) {
prop.type.fullyQualifiedName.toString
} else {
prop.inheritedFeature.^type.fullyQualifiedName.toString
}
}
def dispatch String toQualifiedTypeName(LDtoReference prop) {
prop.type?.fullyQualifiedName.toString
}
def dispatch String toQualifiedTypeName(LDtoInheritedReference prop) {
prop.type?.fullyQualifiedName.toString
}
def dispatch LType toRawType(LFeature prop) {
throw new IllegalStateException("not a valid call")
}
/**
* Returns the type of the property or reference without any mappings
*/
def dispatch LType toRawType(LDtoAttribute prop) {
prop.type
}
/**
* Returns the type of the property or reference without any mappings
*/
def dispatch LType toRawType(LDtoInheritedAttribute prop) {
prop.inheritedFeature?.type
}
/**
* Returns the type of the property or reference without any mappings
*/
def dispatch LType toRawType(LDtoReference prop) {
prop.type
}
/**
* Returns the type of the property or reference without any mappings
*/
def dispatch LType toRawType(LDtoInheritedReference prop) {
prop.inheritedFeature?.toRawType
}
/**
* Returns the type of the property or reference without any mappings
*/
def dispatch LType toRawType(LEntityReference prop) {
prop.type
}
/**
* Returns the type of the property or reference without any mappings
*/
def dispatch LType toRawType(LEntityAttribute prop) {
prop.type
}
/**
* Returns the type of the property or reference without any mappings
*/
def dispatch LType toRawType(LBeanReference prop) {
prop.type
}
/**
* Returns the type of the property or reference without any mappings
*/
def dispatch LType toRawType(LBeanAttribute prop) {
prop.type
}
/**
* Returns the type reference of the property or reference without any mappings
*/
def dispatch toRawTypeRefernce(LDtoFeature prop) {
prop.toRawType?.toTypeReference
}
/**
* Returns the type reference of the property or reference without any mappings
*/
def dispatch toRawTypeRefernce(LDtoInheritedReference prop) {
val LReference ref = prop.inheritedFeature
if (ref instanceof LEntityReference) {
return ref.type.toTypeReference
} else if (ref instanceof LBeanReference) {
return ref.type.toTypeReference
}
return TypesFactory.eINSTANCE.createJvmUnknownTypeReference
}
/**
* Returns the type reference of the property or reference without any mappings
*/
def dispatch toRawTypeRefernce(LDtoAbstractReference prop) {
prop.toRawType?.toTypeReference
}
/**
* Returns the type reference of the property or reference without any mappings
*/
def String toRawTypeName(LDtoFeature prop) {
prop.toRawType?.name
}
def dispatch LFeature opposite(LDtoFeature prop) {
null
}
def dispatch LFeature opposite(LDtoReference prop) {
return prop.opposite
}
def dispatch LFeature opposite(LDtoInheritedReference prop) {
if (prop.inherited && prop.inheritedFeature !== null) {
return prop.inheritedFeature.opposite
} else {
return null
}
}
def dispatch LFeature opposite(LEntityReference prop) {
prop.opposite
}
def dispatch LFeature opposite(LBeanReference prop) {
prop.opposite
}
def dispatch Bounds getBounds(LDtoFeature prop) {
if (prop.inherited) {
return Bounds.createFor(prop.inheritedFeature);
} else {
return Bounds.createFor(prop);
}
}
def dispatch String toName(LDtoFeature feature) {
if(feature === null || !feature.inherited && feature.name === null) return ""
if (feature.inherited) {
return feature.inheritedFeature?.name
}
return feature.name.replace("^", "")
}
def dispatch String toName(LDto dto) {
if (dto === null || dto.name === null) {
return ""
}
return dto.name.replace("^", "")
}
def dispatch String toName(Void param) {
return ""
}
// def dispatch String internalToName(LFeature prop) {
// return prop.name;
// }
//
// def dispatch String internalToName(LDtoFeature prop) {
// if (prop.inherited) {
// return prop.inheritedFeature?.name;
// } else {
// return prop.name;
// }
// }
def dispatch LReference inheritedFeature(LDtoFeature prop) {
return null
}
def dispatch LReference inheritedFeature(LDtoInheritedReference prop) {
return prop.inheritedFeature
}
def dispatch LAttribute inheritedFeature(LDtoInheritedAttribute prop) {
return prop.inheritedFeature
}
override isToMany(LFeature prop) {
if (prop === null) {
return false
}
return internalIsToMany(prop);
}
def dispatch boolean isAbstract(LType context) {
false
}
def dispatch boolean isAbstract(LEntity context) {
context.abstract
}
def dispatch boolean isAbstract(LDto context) {
context.abstract
}
def dispatch boolean isTransient(EObject context) {
false
}
def dispatch boolean isTransient(LDtoAttribute context) {
context.transient
}
def dispatch boolean internalIsToMany(LFeature prop) {
return prop.bounds.toMany;
}
def dispatch boolean internalIsToMany(LDtoFeature prop) {
if (prop.inherited && prop.inheritedFeature !== null) {
return prop.inheritedFeature.internalIsToMany
} else {
return prop.bounds.toMany;
}
}
def dispatch boolean isCascading(LDtoAbstractReference prop) {
if (prop.inherited && prop.inheritedFeature !== null) {
return prop.inheritedFeature.cascading
} else {
return prop.cascading;
}
}
def dispatch boolean isCascading(LDtoAbstractAttribute prop) {
if (prop.inherited && prop.inheritedFeature !== null) {
return prop.inheritedFeature.cascading
} else {
return prop.cascading;
}
}
def isAttribute(LDtoFeature prop) {
return prop instanceof LAttribute
}
def isContainmentReference(LDtoFeature prop) {
return prop instanceof LReference && prop.cascading
}
def isCrossReference(LDtoFeature prop) {
return prop instanceof LReference && !prop.cascading
}
def dispatch isContainerReference(LDtoAbstractAttribute prop) {
return false
}
def dispatch isContainerReference(LDtoOperation prop) {
return false
}
def dispatch isContainerReference(LDtoReference prop) {
val opposite = prop.opposite
if (opposite !== null && opposite.cascading) {
return true
} else if (!prop.bounds.toMany && opposite != null && opposite.bounds.toMany) {
// non containment container ref
return true
}
return false
}
def dispatch isContainerReference(LDtoInheritedReference prop) {
val opposite = prop.inheritedFeature.opposite
if (opposite !== null && opposite.cascading) {
return true
} else if (!prop.bounds.toMany && opposite != null && opposite.bounds.toMany) {
// non containment container ref
return true
}
return false
}
def toMapperTypeReference(LType type) {
references.getTypeForName(type.toFqnMapperName, type, null)
}
def toMapperTypeReference(LDtoAbstractReference ref) {
ref.type.toMapperTypeReference
}
def dispatch isIDorUUID(LAttribute prop) {
return false
}
def dispatch isIDorUUID(LDtoAttribute prop) {
return prop.id || prop.uuid
}
def dispatch isIDorUUID(LDtoInheritedAttribute prop) {
return prop.inheritedFeature.id || prop.inheritedFeature.uuid
}
/**
* Returns all containment features that need to be copied.
*/
def getContainmentReferencesToCopy(LDto dto) {
dto.features.filter [
it.containmentReference
]
}
override boolean isBasedOnDatatype(LFeature feature) {
if (feature instanceof LDtoInheritedAttribute) {
return if(feature.inheritedFeature !== null) feature.inheritedFeature.isBasedOnDatatype else false
}
return super.isBasedOnDatatype(feature)
}
override LDataType getDatatype(LFeature feature) {
if (feature instanceof LDtoInheritedAttribute) {
return if(feature.inheritedFeature !== null) feature.inheritedFeature.getDatatype else null
}
return super.getDatatype(feature)
}
override typeIsEnum(LAttribute prop) {
if (prop instanceof LDtoInheritedAttribute) {
return if(prop.inheritedFeature !== null) prop.inheritedFeature.typeIsEnum else false
}
return super.typeIsEnum(prop)
}
/**
* Returns all attributes that need to be copied.
*/
def getAttributesToCopy(LDto dto) {
dto.features.filter [
it.attribute
]
}
/**
* Returns all crossreferences that need to be copied.
*/
def getCrossReferencesToCopy(LDto dto) {
dto.features.filter [
return !it.containerReference && it.isCrossReference
]
}
def boolean isBean(LType type) {
if (type instanceof LDto) {
return type.wrappedType instanceof LBean
}
return type instanceof LBean
}
def dispatch LAttribute idAttribute(LDto dto) {
for (LDtoAbstractAttribute prop : dto.collectAllAttributes) {
if (prop.inherited && prop.inheritedFeature !== null) {
val LAttribute attribute = prop.inheritedFeature as LAttribute
if (attribute.id || attribute.uuid) {
return attribute
}
} else {
if (prop.id || prop.uuid) {
return prop
}
}
}
}
def dispatch LAttribute idAttribute(LEntity entity) {
for (LEntityAttribute prop : entity.collectAllAttributes) {
if (prop.id || prop.uuid) {
return prop
}
}
}
def Iterable<LDtoAbstractAttribute> collectAllAttributes(LDto dto) {
return dto.allFeatures.filter[it instanceof LDtoAbstractAttribute].map[it as LDtoAbstractAttribute]
}
def Iterable<LEntityAttribute> collectAllAttributes(LEntity entity) {
return entity.allFeatures.filter[it instanceof LEntityAttribute].map[it as LEntityAttribute]
}
}