blob: 3b8c229d98dc3654718d2ed855b45db2203023bd [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 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.io.Serializable
import org.eclipse.emf.ecore.EObject
import org.eclipse.osbp.dsl.common.datatypes.IBean
import org.eclipse.osbp.dsl.common.datatypes.IEntity
import org.eclipse.osbp.dsl.common.xtext.extensions.AnnotationExtension
import org.eclipse.osbp.dsl.entity.xtext.extensions.EntityTypesBuilder
import org.eclipse.osbp.dsl.entity.xtext.extensions.ModelExtensions
import org.eclipse.osbp.dsl.semantic.common.types.LAttribute
import org.eclipse.osbp.dsl.semantic.common.types.LEnum
import org.eclipse.osbp.dsl.semantic.common.types.LReference
import org.eclipse.osbp.dsl.semantic.common.types.LStateClass
import org.eclipse.osbp.dsl.semantic.common.types.LTypedPackage
import org.eclipse.osbp.dsl.semantic.entity.LBean
import org.eclipse.osbp.dsl.semantic.entity.LBeanReference
import org.eclipse.osbp.dsl.semantic.entity.LEntity
import org.eclipse.osbp.dsl.semantic.entity.LEntityReference
import org.eclipse.osbp.dsl.semantic.entity.LOperation
import org.eclipse.osbp.xtext.oxtype.logger.TimeLogger
import org.eclipse.osbp.xtext.oxtype.resource.ExtendedModelInferrer
import org.eclipse.xtext.common.types.JvmDeclaredType
import org.eclipse.xtext.common.types.JvmField
import org.eclipse.xtext.common.types.JvmType
import org.eclipse.xtext.common.types.util.TypeReferences
import org.eclipse.xtext.naming.IQualifiedNameProvider
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.slf4j.Logger
import org.slf4j.LoggerFactory
/**
* This is the main model inferrer that is automatically registered in AbstractEntityRuntimeModule.
* It dispatches to specific model inferrers depending on the metamodel element.
*/
class EntityGrammarJvmModelInferrer extends ExtendedModelInferrer {
protected val Logger log = LoggerFactory::getLogger(getClass())
@Inject AnnotationCompiler annotationCompiler
@Inject extension IQualifiedNameProvider
@Inject extension EntityTypesBuilder;
@Inject extension ModelExtensions;
@Inject TypeReferences references
@Inject AnnotationExtension annExt
// used for test cases with old derived state computer
def dispatch void infer(LStateClass stateClass, IJvmDeclaredTypeAcceptor acceptor, boolean isPrelinkingPhase) {
val type = stateClass.toEnumerationType(stateClass.fullyQualifiedName.toString, null)
type.inferFullState(stateClass, acceptor, isPrelinkingPhase, "")
}
def dispatch void inferTypesOnly(LStateClass stateClass, IJvmDeclaredTypeAcceptor acceptor, boolean isPrelinkingPhase) {
val type = stateClass.toEnumerationType(stateClass.fullyQualifiedName.toString, null)
acceptor.accept(type);
// pass inferring to delegates
inferTypesOnlyByDelegates(stateClass, acceptor, isPrelinkingPhase);
}
def dispatch void inferFullState(JvmDeclaredType type, LStateClass stateClass, IJvmDeclaredTypeAcceptor acceptor,
boolean isPrelinkingPhase, String selector) {
acceptor.accept(type).initializeLater [
val TimeLogger doInferLog = TimeLogger.start(getClass());
annotationCompiler.processAnnotation(stateClass, it);
fileHeader = (stateClass.eContainer as LTypedPackage).documentation
documentation = stateClass.documentation
for (f : stateClass.states) {
documentation = f.documentation
members += f.toEnumerationLiteral(f.name)
}
doInferLog.stop(log, "Inferring stateClass " + stateClass.name)
]
}
def dispatch void infer(LEnum enumX, IJvmDeclaredTypeAcceptor acceptor, boolean isPrelinkingPhase) {
val type = enumX.toEnumerationType(enumX.fullyQualifiedName.toString, null)
type.inferFullState(enumX, acceptor, isPrelinkingPhase, "")
}
def dispatch void inferTypesOnly(LEnum enumX, IJvmDeclaredTypeAcceptor acceptor, boolean isPrelinkingPhase) {
val type = enumX.toEnumerationType(enumX.fullyQualifiedName.toString, null)
acceptor.accept(type);
// pass inferring to delegates
inferTypesOnlyByDelegates(enumX, acceptor, isPrelinkingPhase);
}
def dispatch void inferFullState(JvmDeclaredType type, LEnum enumX, IJvmDeclaredTypeAcceptor acceptor,
boolean isPrelinkingPhase, String selector) {
acceptor.accept(type).initializeLater [
val TimeLogger doInferLog = TimeLogger.start(getClass());
annotationCompiler.processAnnotation(enumX, it);
fileHeader = (enumX.eContainer as LTypedPackage).documentation
documentation = enumX.documentation
for (f : enumX.literals) {
documentation = f.documentation
members += f.toEnumerationLiteral(f.name)
}
doInferLog.stop(log, "Inferring enum " + enumX.name)
]
}
// used for test cases with old derived state computer
def dispatch void infer(LBean bean, IJvmDeclaredTypeAcceptor acceptor, boolean isPrelinkingPhase) {
val type = bean.toJvmType;
type.inferFullState(bean, acceptor, isPrelinkingPhase, "bean")
}
def dispatch void inferTypesOnly(LBean bean, IJvmDeclaredTypeAcceptor acceptor, boolean isPrelinkingPhase) {
val type = bean.toJvmType;
acceptor.accept(type);
// pass inferring to delegates
inferTypesOnlyByDelegates(bean, acceptor, isPrelinkingPhase);
}
def dispatch void inferFullState(JvmDeclaredType type, LBean bean, IJvmDeclaredTypeAcceptor acceptor,
boolean isPrelinkingPhase, String selector) {
if (selector === null || !selector.equals("bean")) {
return
}
acceptor.accept(type).initializeLater [
val TimeLogger doInferLog = TimeLogger.start(getClass());
// mark the type as derived
annotationCompiler.processAnnotation(bean, it);
fileHeader = (bean.eContainer as LTypedPackage).documentation
documentation = bean.getDocumentation
if (bean.getSuperType === null) {
superTypes += references.getTypeForName(typeof(Serializable), bean, null)
}
if (bean.getSuperType !== null && !bean.getSuperType.fullyQualifiedName.toString.empty) {
superTypes += bean.superType.toTypeReference
}
superTypes += references.getTypeForName(typeof(IBean), bean, null)
//
// Constructor
//
members += bean.toConstructor()[]
if (bean.getSuperType === null) {
members += bean.toDiposeField()
members += bean.toDirtyField()
}
//
// Fields
//
for (f : bean.getFeatures) {
switch f {
LAttribute: {
if (!f.derived && f.fullyQualifiedName !== null && !f.fullyQualifiedName.toString.empty) {
members += f.toField
}
}
LReference: {
if (f.fullyQualifiedName !== null && !f.fullyQualifiedName.toString.empty) {
members += f.toField
}
}
}
}
//
// Field accessors
//
if (bean.getSuperType === null) {
members += bean.toIsDisposed()
members += bean.toIsDirty()
members += bean.toSetDirty()
}
members += bean.toCheckDisposed()
members += bean.toDispose()
for (f : bean.getFeatures) {
switch f {
LAttribute: {
members += f.toGetter()
if (!f.derived) {
if (f.isToMany) {
members += f.toCollectionSetter(f.name)
members += f.toInternalCollectionGetter(f.getName)
members += f.toAdder(f.getName)
members += f.toRemover(f.getName)
} else {
members += f.toSetter()
}
}
}
LReference: {
members += f.toGetter()
if (f.isToMany) {
members += f.toCollectionSetter(f.name)
members += f.toInternalCollectionGetter(f.getName)
members += f.toAdder(f.getName)
members += f.toRemover(f.getName)
members += f.toInternalAdder
members += f.toInternalRemover
} else {
members += f.toSetter()
if (f instanceof LBeanReference && (f as LBeanReference).isCascading && (f as LBeanReference).getOpposite !== null) {
members += f.toInternalSetter
}
}
}
}
}
//
// Methods.
//
for (op : bean.operations) {
members += op.toMethod(op.name, op.type) [
documentation = op.documentation
for (p : op.params) {
parameters += p.toParameter(p.name, p.parameterType)
}
body = op.body
]
}
doInferLog.stop(log, "Inferring bean " + bean.name)
]
}
// used for test cases with old derived state computer
def dispatch void infer(LEntity entity, IJvmDeclaredTypeAcceptor acceptor, boolean isPrelinkingPhase) {
val type = entity.toJvmType;
type.inferFullState(entity, acceptor, isPrelinkingPhase, "entity")
}
def dispatch void inferTypesOnly(LEntity entity, IJvmDeclaredTypeAcceptor acceptor, boolean isPrelinkingPhase) {
val type = entity.toJvmType;
acceptor.accept(type);
// pass inferring to delegates
inferTypesOnlyByDelegates(entity, acceptor, isPrelinkingPhase);
}
def dispatch void inferFullState(JvmType type, EObject element, IJvmDeclaredTypeAcceptor acceptor,
boolean isPrelinkingPhase, String selector) {
}
def dispatch void inferFullState(JvmDeclaredType type, LEntity entity, IJvmDeclaredTypeAcceptor acceptor,
boolean isPrelinkingPhase, String selector) {
if (selector === null || !selector.equals("entity")) {
return
}
acceptor.accept(type).initializeLater [
val TimeLogger doInferLog = TimeLogger.start(getClass());
annotationCompiler.processAnnotation(entity, it);
var LAttribute idAttribute = null
var JvmField idField = null
var JvmField versionField = null
fileHeader = (entity.eContainer as LTypedPackage).documentation
documentation = entity.documentation
if (entity.getSuperType !== null && !entity.getSuperType.fullyQualifiedName.toString.empty) {
// superTypes += references.getTypeForName(entity.getSuperType.fullyQualifiedName.toString, entity, null)
superTypes += entity.superType.toTypeReference
}
superTypes += references.getTypeForName(typeof(IEntity), entity, null)
//
// Constructor
//
members += entity.toConstructor()[]
if (entity.getSuperType === null) {
members += entity.toDiposeField()
}
//
// Fields
//
for (f : entity.features.filter[!(it instanceof LOperation)]) {
switch f {
LAttribute: {
if (!f.derived && f.fullyQualifiedName !== null && !f.fullyQualifiedName.toString.empty) {
if (f.id || f.uuid) {
idAttribute = f
idField = f.toField
members += idField
} else if (f.version) {
versionField = f.toField
members += versionField
} else {
members += f.toField
}
}
}
LReference: {
if (f.fullyQualifiedName !== null && !f.fullyQualifiedName.toString.empty) {
members += f.toField
}
}
}
}
// state class handling
if(entity.stateClass !== null) {
members += entity.stateClass.toField()
members += entity.stateClass.toGetter()
members += entity.stateClass.toSetter()
}
//
// Field accessors
//
if (entity.getSuperType === null) {
members += entity.toIsDisposed()
}
members += entity.toCheckDisposed()
members += entity.toDispose()
for (f : entity.features) {
switch f {
LAttribute: {
members += f.toGetter()
if (!f.derived) {
if (f.toMany) {
members += f.toCollectionSetter(f.name)
members += f.toInternalCollectionGetter(f.name)
members += f.toAdder(f.name)
members += f.toRemover(f.name)
} else {
members += f.toSetter()
}
}
}
LReference: {
members += f.toGetter()
if (f.toMany) {
members += f.toCollectionSetter(f.name)
members += f.toInternalCollectionGetter(f.name)
members += f.toAdder(f.name)
members += f.toRemover(f.name)
members += f.toInternalAdder
members += f.toInternalRemover
} else {
members += f.toSetter()
if (f instanceof LEntityReference && (f as LEntityReference).cascading || (f as LEntityReference).opposite !== null) {
members += f.toInternalSetter
}
}
}
}
}
//
// Methods.
//
for (op : entity.operations) {
members += op.toMethod(op.name, op.type) [
documentation = op.documentation
for (p : op.params) {
parameters += p.toParameter(p.name, p.parameterType)
}
body = op.body
]
}
if (idAttribute !== null) {
members += idAttribute.toEqualVersionsMethod(it, false, idField, versionField)
members += idAttribute.toEqualsMethod(it, false, idField)
members += idAttribute.toHashCodeMethod(false, idField)
}
members += entity.toPreRemove
doInferLog.stop(log, "Inferring entity " + entity.name)
]
}
}