/* * $Id$ * * SARL is an general-purpose agent programming language. * More details on http://www.sarl.io * * Copyright (C) 2014-2017 the original authors or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.sarl.lang.mwe2.codebuilder.fragments; import javax.inject.Inject; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.xtend2.lib.StringConcatenationClient; import org.eclipse.xtext.common.types.JvmLowerBound; import org.eclipse.xtext.common.types.JvmParameterizedTypeReference; import org.eclipse.xtext.common.types.JvmUpperBound; import org.eclipse.xtext.common.types.TypesFactory; import org.eclipse.xtext.common.types.access.IJvmTypeProvider; import org.eclipse.xtext.util.EmfFormatter; import org.eclipse.xtext.util.Strings; import org.eclipse.xtext.xbase.lib.Pure; import org.eclipse.xtext.xtext.generator.model.GuiceModuleAccess.BindingFactory; import org.eclipse.xtext.xtext.generator.model.JavaFileAccess; import org.eclipse.xtext.xtext.generator.model.TypeReference; import io.sarl.lang.mwe2.codebuilder.extractor.CodeElementExtractor; /** Generator of the builder for type parameters. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ public class TypeParameterBuilderFragment extends AbstractSubCodeBuilderFragment { /** Replies the implementation for the type parameter builder. * * @return the implementation. */ @Pure public TypeReference getTypeParameterBuilderImpl() { return getCodeElementExtractor().getElementBuilderImpl("TypeParameter"); //$NON-NLS-1$ } /** Replies the custom implementation for the type parameter builder. * * @return the custom implementation. */ @Pure public TypeReference getTypeParameterBuilderImplCustom() { return getCodeElementExtractor().getElementBuilderImplCustom("TypeParameter"); //$NON-NLS-1$ } @Override public void generate() { generateITypeParameterBuilder(); generateTypeParameterBuilderImpl(); if (getCodeBuilderConfig().isISourceAppendableEnable()) { generateTypeParameterAppender(); } super.generate(); } @Override public void generateRuntimeBindings(BindingFactory factory) { super.generateRuntimeBindings(factory); bindTypeReferences(factory, getTypeParameterBuilderInterface(), getTypeParameterBuilderImpl(), getTypeParameterBuilderImplCustom()); } /** Generate the type parameter builder interface. */ protected void generateITypeParameterBuilder() { final TypeReference builder = getTypeParameterBuilderInterface(); final StringConcatenationClient content = new StringConcatenationClient() { @Override protected void appendTo(TargetStringConcatenation it) { it.append("/** Builder of a " + getLanguageName() //$NON-NLS-1$ + " type parameter."); //$NON-NLS-1$ it.newLine(); it.append(" */"); //$NON-NLS-1$ it.newLine(); it.append("@SuppressWarnings(\"all\")"); //$NON-NLS-1$ it.newLine(); it.append("public interface "); //$NON-NLS-1$ it.append(builder.getSimpleName()); it.append(" {"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); it.append(generateMembers(true, false)); it.append("}"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); } }; final JavaFileAccess javaFile = getFileAccessFactory().createJavaFile(builder, content); javaFile.writeTo(getSrcGen()); } /** Generate the formal parameter builder implementation. */ protected void generateTypeParameterBuilderImpl() { final TypeReference builderInterface = getTypeParameterBuilderInterface(); final TypeReference builder = getTypeParameterBuilderImpl(); final StringConcatenationClient content = new StringConcatenationClient() { @Override protected void appendTo(TargetStringConcatenation it) { it.append("/** Builder of a " + getLanguageName() //$NON-NLS-1$ + " type parameter."); //$NON-NLS-1$ it.newLine(); it.append(" */"); //$NON-NLS-1$ it.newLine(); it.append("@SuppressWarnings(\"all\")"); //$NON-NLS-1$ it.newLine(); it.append("public class "); //$NON-NLS-1$ it.append(builder.getSimpleName()); it.append(" extends "); //$NON-NLS-1$ it.append(getAbstractBuilderImpl()); it.append(" implements "); //$NON-NLS-1$ it.append(builderInterface); it.append(" {"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); it.append(generateMembers(false, false)); it.append("}"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); } }; final JavaFileAccess javaFile = getFileAccessFactory().createJavaFile(builder, content); javaFile.writeTo(getSrcGen()); } /** Generate the formal parameter appender. */ protected void generateTypeParameterAppender() { final CodeElementExtractor.ElementDescription parameter = getCodeElementExtractor().getTypeParameter(); final String accessor = "get" //$NON-NLS-1$ + Strings.toFirstUpper(parameter.getElementType().getSimpleName()) + "()"; //$NON-NLS-1$ final TypeReference builderInterface = getTypeParameterBuilderInterface(); final TypeReference appender = getCodeElementExtractor().getElementAppenderImpl("TypeParameter"); //$NON-NLS-1$ final StringConcatenationClient content = new StringConcatenationClient() { @Override protected void appendTo(TargetStringConcatenation it) { it.append("/** Appender of a " + getLanguageName() //$NON-NLS-1$ + " type parameter."); //$NON-NLS-1$ it.newLine(); it.append(" */"); //$NON-NLS-1$ it.newLine(); it.append("@SuppressWarnings(\"all\")"); //$NON-NLS-1$ it.newLine(); it.append("public class "); //$NON-NLS-1$ it.append(appender.getSimpleName()); it.append(" extends "); //$NON-NLS-1$ it.append(getCodeElementExtractor().getAbstractAppenderImpl()); it.append(" implements "); //$NON-NLS-1$ it.append(builderInterface); it.append(" {"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); it.append(generateAppenderMembers(appender.getSimpleName(), builderInterface, accessor)); it.append(generateMembers(false, true)); it.append("}"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); } }; final JavaFileAccess javaFile = getFileAccessFactory().createJavaFile(appender, content); javaFile.writeTo(getSrcGen()); } /** Generate the members of the builder. * * @param forInterface <code>true</code> if the code must be generated for an interface. * @param forAppender <code>true</code> if the code must be generated for an appender. * @return the code. */ @SuppressWarnings("checkstyle:all") protected StringConcatenationClient generateMembers(boolean forInterface, boolean forAppender) { final CodeElementExtractor.ElementDescription parameter = getCodeElementExtractor().getTypeParameter(); return new StringConcatenationClient() { @Override protected void appendTo(TargetStringConcatenation it) { if (!forInterface && !forAppender) { it.append("\tprivate "); //$NON-NLS-1$ it.append(EObject.class); it.append(" context;"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); it.append("\tprivate "); //$NON-NLS-1$ it.append(parameter.getElementType()); it.append(" parameter;"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); it.append("\t@"); //$NON-NLS-1$ it.append(Inject.class); it.newLine(); it.append("\t\tprivate "); //$NON-NLS-1$ it.append(TypesFactory.class); it.append(" jvmTypesFactory;"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); } else { it.append("\t/** Find the reference to the type with the given name."); //$NON-NLS-1$ it.newLine(); it.append("\t * @param typeName the fully qualified name of the type"); //$NON-NLS-1$ it.newLine(); it.append("\t * @return the type reference."); //$NON-NLS-1$ it.newLine(); it.append("\t */"); //$NON-NLS-1$ it.newLine(); it.append("\t"); //$NON-NLS-1$ if (!forInterface) { it.append("public "); //$NON-NLS-1$ } it.append(JvmParameterizedTypeReference.class); it.append(" newTypeRef(String typeName)"); //$NON-NLS-1$ if (forInterface) { it.append(";"); //$NON-NLS-1$ } else { it.append(" {"); //$NON-NLS-1$ it.newLine(); it.append("\t\treturn this.builder.newTypeRef(typeName);"); //$NON-NLS-1$ it.newLine(); it.append("\t}"); //$NON-NLS-1$ } it.newLineIfNotEmpty(); it.newLine(); it.append("\t/** Find the reference to the type with the given name."); //$NON-NLS-1$ it.newLine(); it.append("\t * @param context the context for the type reference use"); //$NON-NLS-1$ it.newLine(); it.append("\t * @param typeName the fully qualified name of the type"); //$NON-NLS-1$ it.newLine(); it.append("\t * @return the type reference."); //$NON-NLS-1$ it.newLine(); it.append("\t */"); //$NON-NLS-1$ it.newLine(); it.append("\t"); //$NON-NLS-1$ if (!forInterface) { it.append("public "); //$NON-NLS-1$ } it.append(JvmParameterizedTypeReference.class); it.append(" newTypeRef("); //$NON-NLS-1$ it.append(Notifier.class); it.append(" context, String typeName)"); //$NON-NLS-1$ if (forInterface) { it.append(";"); //$NON-NLS-1$ } else { it.append(" {"); //$NON-NLS-1$ it.newLine(); it.append("\t\treturn this.builder.newTypeRef(context, typeName);"); //$NON-NLS-1$ it.newLine(); it.append("\t}"); //$NON-NLS-1$ } it.newLineIfNotEmpty(); it.newLine(); } it.append("\t/** Initialize the type parameter."); //$NON-NLS-1$ it.newLine(); it.append("\t * <p>Caution: This initialization function does not add the type parameter in its container."); //$NON-NLS-1$ it.newLine(); it.append("\t * The container is responsible of adding the type parameter in its internal object."); //$NON-NLS-1$ it.newLine(); it.append("\t * @param name - the name of the type parameter."); //$NON-NLS-1$ it.newLine(); it.append("\t * @param typeContext - the provider of types or null."); //$NON-NLS-1$ it.newLine(); it.append("\t */"); //$NON-NLS-1$ it.newLine(); it.append("\t"); //$NON-NLS-1$ if (!forInterface) { it.append("public "); //$NON-NLS-1$ } it.append("void eInit("); //$NON-NLS-1$ it.append(EObject.class); it.append(" context, String name, "); //$NON-NLS-1$ it.append(IJvmTypeProvider.class); it.append(" typeContext)"); //$NON-NLS-1$ if (forInterface) { it.append(";"); //$NON-NLS-1$ } else { it.append(" {"); //$NON-NLS-1$ it.newLine(); if (forAppender) { it.append("\t\tthis.builder.eInit(context, name, typeContext);"); //$NON-NLS-1$ } else { it.append("\t\tsetTypeResolutionContext(typeContext);"); //$NON-NLS-1$ it.newLine(); it.append("\t\tthis.context = context;"); //$NON-NLS-1$ it.newLine(); it.append("\t\tthis.parameter = this.jvmTypesFactory.create"); //$NON-NLS-1$ it.append(Strings.toFirstUpper(parameter.getElementType().getSimpleName())); it.append("();"); //$NON-NLS-1$ it.newLine(); it.append("\t\tthis.parameter.set"); //$NON-NLS-1$ it.append(Strings.toFirstUpper(getCodeBuilderConfig().getParameterNameGrammarName())); it.append("(name);"); //$NON-NLS-1$ it.newLine(); } it.newLine(); it.append("\t}"); //$NON-NLS-1$ } it.newLineIfNotEmpty(); it.newLine(); if (forInterface) { it.append("\t/** Replies the context for type resolution."); //$NON-NLS-1$ it.newLine(); it.append("\t * @return the context or <code>null</code> if the Ecore object is the context."); //$NON-NLS-1$ it.newLine(); it.append("\t */"); //$NON-NLS-1$ it.newLine(); it.append("\t"); //$NON-NLS-1$ it.append(IJvmTypeProvider.class); it.append(" getTypeResolutionContext();"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); } else if (forAppender) { it.append("\tpublic "); //$NON-NLS-1$ it.append(IJvmTypeProvider.class); it.append(" getTypeResolutionContext() {"); //$NON-NLS-1$ it.newLine(); it.append("\t\treturn this.builder.getTypeResolutionContext();"); //$NON-NLS-1$ it.newLine(); it.append("\t}"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); } it.append("\t/** Replies the created parameter."); //$NON-NLS-1$ it.newLine(); it.append("\t *"); //$NON-NLS-1$ it.newLine(); it.append("\t * @return the parameter."); //$NON-NLS-1$ it.newLine(); it.append("\t */"); //$NON-NLS-1$ it.newLine(); it.append("\t@"); //$NON-NLS-1$ it.append(Pure.class); it.newLine(); it.append("\t"); //$NON-NLS-1$ if (!forInterface) { it.append("public "); //$NON-NLS-1$ } it.append(parameter.getElementType()); it.append(" get"); //$NON-NLS-1$ it.append(Strings.toFirstUpper(parameter.getElementType().getSimpleName())); it.append("()"); //$NON-NLS-1$ if (forInterface) { it.append(";"); //$NON-NLS-1$ } else { it.append(" {"); //$NON-NLS-1$ it.newLine(); if (forAppender) { it.append("\t\treturn this.builder.get"); //$NON-NLS-1$ it.append(Strings.toFirstUpper(parameter.getElementType().getSimpleName())); it.append("();"); //$NON-NLS-1$ } else { it.append("\t\treturn this.parameter;"); //$NON-NLS-1$ } it.newLine(); it.append("\t}"); //$NON-NLS-1$ } it.newLineIfNotEmpty(); it.newLine(); it.append("\t/** Replies the resource to which the type parameter is attached."); //$NON-NLS-1$ it.newLine(); it.append("\t */"); //$NON-NLS-1$ it.newLine(); it.append("\t@"); //$NON-NLS-1$ it.append(Pure.class); it.newLine(); it.append("\t"); //$NON-NLS-1$ if (!forInterface) { it.append("public "); //$NON-NLS-1$ } it.append(Resource.class); it.append(" eResource()"); //$NON-NLS-1$ if (forInterface) { it.append(";"); //$NON-NLS-1$ } else { it.append(" {"); //$NON-NLS-1$ it.newLine(); it.append("\t\treturn get"); //$NON-NLS-1$ it.append(Strings.toFirstUpper(parameter.getElementType().getSimpleName())); it.append("().eResource();"); //$NON-NLS-1$ it.newLine(); it.append("\t}"); //$NON-NLS-1$ } it.newLineIfNotEmpty(); it.newLine(); if (!forAppender && !forInterface) { it.append("\t@"); //$NON-NLS-1$ it.append(Override.class); it.newLine(); it.append("\t@"); //$NON-NLS-1$ it.append(Pure.class); it.newLine(); it.append("\tpublic "); //$NON-NLS-1$ it.append(String.class); it.append(" toString() {"); //$NON-NLS-1$ it.newLine(); it.append("\t\treturn "); //$NON-NLS-1$ if (forAppender) { it.append("this.builder.toString();"); //$NON-NLS-1$ } else { it.append(EmfFormatter.class); it.append(".objToStr(get"); //$NON-NLS-1$ it.append(Strings.toFirstUpper(parameter.getElementType().getSimpleName())); it.append("());"); //$NON-NLS-1$ } it.newLine(); it.append("\t}"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); } if (forInterface) { it.append("\t/** Dispose the resource."); //$NON-NLS-1$ it.newLine(); it.append("\t */"); //$NON-NLS-1$ it.newLine(); it.append("\tvoid dispose();"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); } else if (forAppender) { it.append("\t/** Dispose the resource."); //$NON-NLS-1$ it.newLine(); it.append("\t */"); //$NON-NLS-1$ it.newLine(); it.append("\tpublic void dispose() {"); //$NON-NLS-1$ it.newLine(); it.append("\t\tthis.builder.dispose();"); //$NON-NLS-1$ it.newLine(); it.append("\t}"); //$NON-NLS-1$ it.newLineIfNotEmpty(); it.newLine(); } it.append("\t/** Add upper type bounds."); //$NON-NLS-1$ it.newLine(); it.append("\t * @param type the type."); //$NON-NLS-1$ it.newLine(); it.append("\t */"); //$NON-NLS-1$ it.newLine(); it.append("\t"); //$NON-NLS-1$ if (!forInterface) { it.append("public "); //$NON-NLS-1$ } it.append("void addUpperConstraint(String type)"); //$NON-NLS-1$ if (forInterface) { it.append(";"); //$NON-NLS-1$ } else { it.append(" {"); //$NON-NLS-1$ it.newLine(); it.append("\t\t"); //$NON-NLS-1$ if (forAppender) { it.append("this.builder.addUpperConstraint(type);"); //$NON-NLS-1$ } else { it.append("final "); //$NON-NLS-1$ it.append(JvmUpperBound.class); it.append(" constraint = this.jvmTypesFactory.createJvmUpperBound();"); //$NON-NLS-1$ it.newLine(); it.append("\t\tconstraint.setTypeReference(newTypeRef(this.context, type));"); //$NON-NLS-1$ it.newLine(); it.append("\t\tget"); //$NON-NLS-1$ it.append(Strings.toFirstUpper(parameter.getElementType().getSimpleName())); it.append("().getConstraints().add(constraint);"); //$NON-NLS-1$ } it.newLine(); it.append("\t}"); //$NON-NLS-1$ } it.newLineIfNotEmpty(); it.newLine(); it.append("\t/** Add lower type bounds."); //$NON-NLS-1$ it.newLine(); it.append("\t * @param type the type."); //$NON-NLS-1$ it.newLine(); it.append("\t */"); //$NON-NLS-1$ it.newLine(); it.append("\t"); //$NON-NLS-1$ if (!forInterface) { it.append("public "); //$NON-NLS-1$ } it.append("void addLowerConstraint(String type)"); //$NON-NLS-1$ if (forInterface) { it.append(";"); //$NON-NLS-1$ } else { it.append(" {"); //$NON-NLS-1$ it.newLine(); it.append("\t\t"); //$NON-NLS-1$ if (forAppender) { it.append("this.builder.addLowerConstraint(type);"); //$NON-NLS-1$ } else { it.append("final "); //$NON-NLS-1$ it.append(JvmLowerBound.class); it.append(" constraint = this.jvmTypesFactory.createJvmLowerBound();"); //$NON-NLS-1$ it.newLine(); it.append("\t\tconstraint.setTypeReference(newTypeRef(this.context, type));"); //$NON-NLS-1$ it.newLine(); it.append("\t\tget"); //$NON-NLS-1$ it.append(Strings.toFirstUpper(parameter.getElementType().getSimpleName())); it.append("().getConstraints().add(constraint);"); //$NON-NLS-1$ } it.newLine(); it.append("\t}"); //$NON-NLS-1$ } it.newLineIfNotEmpty(); it.newLine(); } }; } }