| /** |
| * |
| * 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 v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * 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 org.eclipse.osbp.xtext.messagedsl.MessageCategory |
| import org.eclipse.osbp.xtext.messagedsl.MessageGroup |
| 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.common.AMessageGroup |
| 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.naming.IQualifiedNameProvider |
| 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 |
| import org.eclipse.osbp.ui.api.metadata.IDSLMetadataService |
| import org.eclipse.xtext.common.types.JvmType |
| import java.util.Locale |
| import org.eclipse.xtext.common.types.JvmGenericType |
| import org.eclipse.xtext.common.types.JvmField |
| import javax.annotation.PostConstruct |
| import javax.inject.Inject |
| import com.google.common.base.CaseFormat |
| import org.eclipse.osbp.xtext.messagedsl.MessageDefaultFormat |
| import org.eclipse.osbp.ui.api.user.IUser |
| |
| /** |
| * <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) |
| superTypes += _typeReferenceBuilder.typeRef(IUser.UserLocaleListener) |
| // @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.toFields(model) |
| it.toOperations(model) |
| category.groups.forEach [ group | |
| it.addMessageGroup(model, category, group, acceptor) |
| group.items.forEach [ item | |
| it.members += toMethod(false, model, category, group, item, acceptor) |
| it.members += toMethod(true, model, category, group, item, acceptor) |
| ] |
| ] |
| ] |
| ] |
| } |
| |
| def toOperations(JvmGenericType type, MessageModel model) { |
| type.members += model.toMethod("registerLocaleListener", _typeReferenceBuilder.typeRef(Void::TYPE), |
| [ |
| visibility = JvmVisibility.PROTECTED |
| annotations += _annotationTypesBuilder.annotationRef(PostConstruct) |
| body = [append('''user.addUserLocaleListener(this);''')] |
| ]) |
| type.members += model.toMethod("localeChanged", _typeReferenceBuilder.typeRef(Void::TYPE), |
| [ |
| visibility = JvmVisibility.PUBLIC |
| annotations += _annotationTypesBuilder.annotationRef(Override) |
| parameters += model.toParameter("locale", _typeReferenceBuilder.typeRef(Locale)) |
| body = [append('''this.locale = locale;''')] |
| ]) |
| } |
| |
| def toFields(JvmGenericType type, MessageModel model) { |
| var JvmField field = null |
| field = model.toField("dslMetadataService", _typeReferenceBuilder.typeRef(IDSLMetadataService))[ |
| annotations += _annotationTypesBuilder.annotationRef(Inject)] |
| field.static = true |
| type.members += field |
| field = model.toField("user", _typeReferenceBuilder.typeRef(IUser))[ |
| annotations += _annotationTypesBuilder.annotationRef(Inject)] |
| type.members += field |
| field = model.toField("locale", _typeReferenceBuilder.typeRef(Locale)) |
| field.static = true |
| type.members += field |
| } |
| |
| /** |
| * <p>build the inner class UiProvider.</p> |
| * |
| */ |
| def void addMessageGroup(JvmDeclaredType type, MessageModel model, MessageCategory category, MessageGroup group, |
| IJvmDeclaredTypeAcceptor acceptor) { |
| var cls = model.toClass(group.name) |
| type.members += cls |
| cls.superTypes += _typeReferenceBuilder.typeRef(typeof(AMessageGroup)) |
| cls.static = true |
| cls.members += model.toConstructor( |
| [ |
| body = [append('''super(«category.getSimpleMessageClass».class);''')] |
| ]) |
| |
| var field = model.toField('''s«group.name»''', _typeReferenceBuilder.typeRef(AMessageGroup)); |
| type.members += field |
| field.visibility = JvmVisibility.PRIVATE |
| field.static = true |
| field.final = true |
| field.setInitializer([append('''new «group.name»()''')]) |
| } |
| |
| /** |
| * 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.eContainer as MessageCategory).getFQMessageClass |
| } |
| |
| /** |
| * return the generated method name for the message item |
| */ |
| public def static String getMethodName(MessageItem item) { |
| return item.itemName |
| } |
| |
| /** |
| * return the generated item name for the message item, used for i18n |
| */ |
| public def static String getItemName(MessageItem item) { |
| return '''«(item.eContainer as MessageGroup).name»_«item.name»''' |
| } |
| |
| def JvmOperation toMethod(boolean withLogger, MessageModel model, MessageCategory category, MessageGroup group, |
| MessageItem item, IJvmDeclaredTypeAcceptor acceptor) { |
| return model.toMethod('''«item.itemName»''', _typeReferenceBuilder.typeRef(Message)) [ |
| val fqMessageClass = item.FQMessageClass |
| val itemName = item.itemName |
| // val i18nKey = BasicTranslator.getTranslatorKey(messageClass, itemName) |
| var docCompiled = "" as String |
| if (group.documentation instanceof String) { |
| docCompiled = '''«docCompiled» |
| «group.documentation»<br> |
| ''' |
| } |
| if (item.documentation instanceof String) { |
| docCompiled = '''«docCompiled» |
| «item.documentation»<br> |
| ''' |
| } |
| if (!item.automaticOutputs.empty) { |
| docCompiled = '''«docCompiled» |
| Automatic output of this message as<ul> |
| ''' |
| } |
| for (automaticOutput : item.automaticOutputs) { |
| docCompiled = '''«docCompiled» |
| <li>«automaticOutput»</li> |
| ''' |
| } |
| if (!item.automaticOutputs.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 bodyCompiled = ''' |
| return ( |
| new Message(dslMetadataService, locale, «logger»«fqMessageClass».class, s«group.name», "«itemName»"''' |
| if ((item.logFormat != null) && (item.showFormat != null)) { |
| bodyCompiled = '''«bodyCompiled» |
| , "«item.logFormat.escapedFormat»" |
| , "«item.showFormat.escapedFormat»" |
| ''' |
| } else { |
| bodyCompiled = '''«bodyCompiled» |
| , "«item.allFormat.escapedFormat»" |
| , "«item.allFormat.escapedFormat»" |
| ''' |
| } |
| 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 (automaticOutput : item.automaticOutputs) { |
| bodyCompiled = '''«bodyCompiled» |
| .«CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, automaticOutput.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(MessageDefaultFormat defaultFormat) { |
| return defaultFormat.format.replaceAll('''\n''', '''\\n''').replaceAll('''\t''', '''\\t'''); |
| } |
| } |