| /** |
| * |
| * Copyright (c) 2011, 2016 - 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: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| * |
| * |
| * This copyright notice shows up in the generated Java code |
| * |
| */ |
| package org.eclipse.osbp.xtext.messagedsl.jvmmodel |
| |
| import com.google.common.base.CaseFormat |
| import javax.inject.Inject |
| import org.eclipse.osbp.xtext.messagedsl.MessageCategory |
| import org.eclipse.osbp.xtext.messagedsl.MessageItem |
| import org.eclipse.osbp.xtext.messagedsl.MessageModel |
| import org.eclipse.osbp.xtext.messagedsl.MessagePackage |
| import org.eclipse.osbp.xtext.messagedsl.MessageText |
| import org.eclipse.osbp.xtext.messagedsl.common.IMessageCategory |
| import org.eclipse.osbp.xtext.messagedsl.common.Message |
| import org.eclipse.xtext.common.types.JvmDeclaredType |
| import org.eclipse.xtext.common.types.JvmOperation |
| import org.eclipse.xtext.common.types.JvmVisibility |
| import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer |
| import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor |
| import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor.IPostIndexingInitializing |
| import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder |
| import org.slf4j.Logger |
| |
| /** |
| * <p>Infers a JVM model from the source model.</p> |
| * |
| * <p>The JVM model should contain all elements that would appear in the Java code |
| * which is generated from the source model. Other models link against the JVM model rather than the source model.</p> |
| */ |
| class MessageDslJvmModelInferrer extends AbstractModelInferrer { |
| |
| /** |
| * convenience API to build and initialize JVM types and their members. |
| */ |
| @Inject extension JvmTypesBuilder |
| |
| /** |
| * The dispatch method {@code infer} is called for each instance of the |
| * given element's type that is contained in a resource. |
| * |
| * @param element |
| * the model to create one or more |
| * {@link JvmDeclaredType declared |
| * types} from. |
| * @param acceptor |
| * each created |
| * {@link JvmDeclaredType type} |
| * without a container should be passed to the acceptor in order |
| * get attached to the current resource. The acceptor's |
| * {@link IJvmDeclaredTypeAcceptor#accept(org.eclipse.xtext.common.types.JvmDeclaredType) |
| * accept(..)} method takes the constructed empty type for the |
| * pre-indexing phase. This one is further initialized in the |
| * indexing phase using the closure you pass to the returned |
| * {@link IPostIndexingInitializing#initializeLater(org.eclipse.xtext.xbase.lib.Procedures.Procedure1) |
| * initializeLater(..)}. |
| * @param isPreIndexingPhase |
| * whether the method is called in a pre-indexing phase, i.e. |
| * when the global index is not yet fully updated. You must not |
| * rely on linking using the index if isPreIndexingPhase is |
| * <code>true</code>. |
| */ |
| def dispatch void infer(MessageModel model, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) { |
| model.pckg.categories.forEach [ category | |
| acceptor.accept(model.toClass('''«category.getFQMessageClass»''')) [ |
| superTypes += _typeReferenceBuilder.typeRef(IMessageCategory) |
| // @see org.eclipse.osbp.utils.constants.GeneratorConstants.GeneratorConstants |
| documentation = '''<b>This class was auto generated! Leave it unmodified to avoid unpredictable results!</b><br> |
| «category.documentation» |
| ''' |
| final = true |
| it.fileHeader = model.pckg.documentation |
| category.items.forEach [ item | |
| it.members += toMethod(false, model, category, item, acceptor) |
| it.members += toMethod(true, model, category, item, acceptor) |
| ] |
| ] |
| ] |
| } |
| |
| /** |
| * return the simple generated class name for the message category |
| */ |
| public def static String getSimpleMessageClass(MessageCategory category) { |
| return '''«category.name»Message''' |
| } |
| |
| /** |
| * return the fully qualified generated class name for the message category |
| */ |
| public def static String getFQMessageClass(MessageCategory category) { |
| return '''«(category.eContainer as MessagePackage).name».«category.getSimpleMessageClass»''' |
| } |
| |
| /** |
| * return the fully qualified generated class name for the message item |
| */ |
| public def static String getFQMessageClass(MessageItem item) { |
| return (item.eContainer as MessageCategory).getFQMessageClass |
| } |
| |
| /** |
| * return the generated method name for the message item |
| */ |
| public def static String getMethodName(MessageItem item) { |
| return item.name |
| } |
| |
| def JvmOperation toMethod(boolean withLogger, MessageModel model, MessageCategory category, |
| MessageItem item, IJvmDeclaredTypeAcceptor acceptor) { |
| return model.toMethod('''«item.name.toFirstLower»''', _typeReferenceBuilder.typeRef(Message)) [ |
| val fqMessageClass = item.FQMessageClass |
| var docCompiled = "" as String |
| if (item.documentation instanceof String) { |
| docCompiled = '''«docCompiled» |
| «item.documentation»<br> |
| ''' |
| } |
| if (!item.severities.empty) { |
| docCompiled = '''«docCompiled» |
| Severity of this message as<ul> |
| ''' |
| } |
| for (severity : item.severities) { |
| docCompiled = '''«docCompiled» |
| <li>«severity»</li> |
| ''' |
| } |
| if (!item.severities.empty) { |
| docCompiled = '''«docCompiled» |
| </ul> |
| ''' |
| } |
| var logger = "" as String |
| if (withLogger) { |
| docCompiled = '''«docCompiled» |
| @param logger set the slf4j logger used when logging this message |
| ''' |
| parameters += model.toParameter("logger", _typeReferenceBuilder.typeRef(Logger)) |
| logger = "logger," |
| } else { |
| docCompiled = '''«docCompiled» |
| the default logger «fqMessageClass» will be used |
| ''' |
| } |
| var bodyCompiledHasParam=false |
| var bodyCompiled = ''' |
| return ( |
| new Message(«logger»''' |
| if (item.logOutput !== null) { |
| bodyCompiled = '''«bodyCompiled» |
| "«item.logOutput.escapedFormat»" |
| , "" |
| ''' |
| bodyCompiledHasParam=true |
| } |
| if (item.showOutput !== null) { |
| bodyCompiled = '''«bodyCompiled» |
| «IF bodyCompiledHasParam», «ENDIF»"" |
| , "«item.showOutput.escapedFormat»" |
| ''' |
| bodyCompiledHasParam=true |
| } |
| if (item.allOutput !== null) { |
| bodyCompiled = '''«bodyCompiled» |
| «IF bodyCompiledHasParam», «ENDIF»"«item.allOutput.escapedFormat»" |
| , "«item.allOutput.escapedFormat»" |
| ''' |
| bodyCompiledHasParam=true |
| } |
| for (parameter : item.parameters) { |
| var typeRef = _typeReferenceBuilder.typeRef(String) |
| switch (parameter.oftype) { |
| case BOOLEAN: typeRef = _typeReferenceBuilder.typeRef(typeof(boolean)) |
| case CLASS: typeRef = _typeReferenceBuilder.typeRef(typeof(Class)) |
| case DOUBLE: typeRef = _typeReferenceBuilder.typeRef(typeof(double)) |
| case EXCEPTION: typeRef = _typeReferenceBuilder.typeRef(Exception) |
| case INTEGER: typeRef = _typeReferenceBuilder.typeRef(typeof(int)) |
| case OBJECT: typeRef = _typeReferenceBuilder.typeRef(typeof(Object)) |
| default: _typeReferenceBuilder.typeRef(String) |
| } |
| parameters += model.toParameter(parameter.name, typeRef) |
| docCompiled = '''«docCompiled» |
| @param «parameter.name» «parameter.documentation» |
| ''' |
| bodyCompiled = '''«bodyCompiled» |
| , "«parameter.name»", «parameter.name» |
| ''' |
| } |
| bodyCompiled = '''«bodyCompiled»)) |
| ''' |
| for (severity : item.severities) { |
| bodyCompiled = '''«bodyCompiled» |
| .«CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, severity.toString.replace('-', '_'))»() |
| ''' |
| } |
| bodyCompiled = '''«bodyCompiled»;''' |
| if (item.documentation instanceof String) { |
| docCompiled = '''«docCompiled» |
| @return instance of Message, which can be used any further |
| ''' |
| } |
| static = true |
| final = true |
| visibility = JvmVisibility.PUBLIC |
| documentation = docCompiled.trim |
| val theBody = bodyCompiled |
| body = [append('''«theBody»''')] |
| ] |
| } |
| |
| def String escapedFormat(MessageText msg) { |
| return msg.text.replaceAll('''\n''', '''\\n''').replaceAll('''\t''', '''\\t'''); |
| } |
| } |