| /** |
| * 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 java.util.Date |
| import org.eclipse.emf.ecore.EObject |
| import org.eclipse.emf.ecore.util.EcoreUtil |
| 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.LDataType |
| 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.LTypedPackage |
| import org.eclipse.osbp.dsl.semantic.common.types.OSBPTypesFactory |
| 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.dsl.semantic.entity.OSBPEntityFactory |
| 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(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()); |
| |
| 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.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 |
| } |
| } |
| } |
| } |
| // |
| // 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.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) |
| |
| ] |
| } |
| } |