/*
* $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 java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Provider;
import com.google.inject.Injector;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtend2.lib.StringConcatenationClient;
import org.eclipse.xtext.common.types.JvmDeclaredType;
import org.eclipse.xtext.common.types.JvmParameterizedTypeReference;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.access.IJvmTypeProvider;
import org.eclipse.xtext.generator.IFileSystemAccess2;
import org.eclipse.xtext.resource.DerivedStateAwareResource;
import org.eclipse.xtext.util.EmfFormatter;
import org.eclipse.xtext.util.Strings;
import org.eclipse.xtext.xbase.compiler.ISourceAppender;
import org.eclipse.xtext.xbase.compiler.ImportManager;
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 org.eclipse.xtext.xtext.generator.model.XtendFileAccess;
import org.eclipse.xtext.xtype.XImportDeclaration;
import org.eclipse.xtext.xtype.XImportSection;
import org.eclipse.xtext.xtype.XtypeFactory;
import io.sarl.lang.mwe2.codebuilder.extractor.CodeElementExtractor;
/** Generator of the script builder types.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
public class ScriptBuilderFragment extends AbstractSubCodeBuilderFragment {
@Inject
private BuilderFactoryContributions builderFactoryContributions;
/** Replies the custom implementation for the script builder.
*
* @return the implementation.
*/
@Pure
public TypeReference getScriptBuilderImplCustom() {
return new TypeReference(getCodeElementExtractor().getBuilderPackage() + ".ScriptBuilderImplCustom"); //$NON-NLS-1$
}
/** Replies the implementation for the builder of scripts.
*
* @return the implementation.
*/
@Pure
public TypeReference getScriptBuilderImpl() {
return new TypeReference(getCodeElementExtractor().getBuilderPackage() + ".ScriptBuilderImpl"); //$NON-NLS-1$
}
/** Replies the appender for the scripts.
*
* @return the appender
*/
public TypeReference getScriptAppender() {
return getCodeElementExtractor().getElementAppenderImpl("Script"); //$NON-NLS-1$
}
@Override
protected Collection<AbstractSubCodeBuilderFragment> initializeSubGenerators(Injector injector) {
return Arrays.asList(
injector.getInstance(ExpressionBuilderFragment.class),
injector.getInstance(BlockExpressionBuilderFragment.class),
injector.getInstance(FormalParameterBuilderFragment.class),
injector.getInstance(TypeParameterBuilderFragment.class),
injector.getInstance(TopElementBuilderFragment.class));
}
@Override
public void generate() {
generateIScriptBuilder();
generateScriptBuilderImpl();
generateScriptSourceAppender();
generateBuilderFactoryContributions();
super.generate();
}
@Override
public void generateRuntimeBindings(BindingFactory factory) {
super.generateRuntimeBindings(factory);
bindTypeReferences(factory, getScriptBuilderInterface(), getScriptBuilderImpl(), getScriptBuilderImplCustom());
}
/** Generate the contributions for the BuildFactory.
*/
@SuppressWarnings("checkstyle:all")
protected void generateBuilderFactoryContributions() {
final boolean enableAppenders = getCodeBuilderConfig().isISourceAppendableEnable();
this.builderFactoryContributions.addContribution(new StringConcatenationClient() {
@Override
protected void appendTo(TargetStringConcatenation it) {
it.append("\t/** Create the factory for a " + getLanguageName() + " script."); //$NON-NLS-1$ //$NON-NLS-2$
it.newLine();
it.append("\t * @param packageName the name of the package of the script."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param resourceSet the resource set in which the script is created."); //$NON-NLS-1$
it.newLine();
it.append("\t * @return the factory."); //$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("\tpublic "); //$NON-NLS-1$
it.append(getScriptBuilderInterface());
it.append(" createScript(String packageName, "); //$NON-NLS-1$
it.append(ResourceSet.class);
it.append(" resourceSet) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\treturn createScript(packageName, createResource(resourceSet), null);"); //$NON-NLS-1$
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append("\t/** Create the factory for a " + getLanguageName() + " script."); //$NON-NLS-1$ //$NON-NLS-2$
it.newLine();
it.append("\t * @param packageName the name of the package of the script."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param resource the resource in which the script is created."); //$NON-NLS-1$
it.newLine();
it.append("\t * @return the factory."); //$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("\tpublic "); //$NON-NLS-1$
it.append(getScriptBuilderInterface());
it.append(" createScript(String packageName, "); //$NON-NLS-1$
it.append(Resource.class);
it.append(" resource) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\treturn createScript(packageName, resource, null);"); //$NON-NLS-1$
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append("\t/** Create the factory for a " + getLanguageName() + " script."); //$NON-NLS-1$ //$NON-NLS-2$
it.newLine();
it.append("\t * @param packageName the name of the package of the script."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param resource the resource in which the script is created."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param context the context for type resolution."); //$NON-NLS-1$
it.newLine();
it.append("\t * @return the factory."); //$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("\tpublic "); //$NON-NLS-1$
it.append(getScriptBuilderInterface());
it.append(" createScript(String packageName, "); //$NON-NLS-1$
it.append(Resource.class);
it.append(" resource, "); //$NON-NLS-1$
it.append(IJvmTypeProvider.class);
it.append(" context) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t"); //$NON-NLS-1$
it.append(getScriptBuilderInterface());
it.append(" builder = getProvider("); //$NON-NLS-1$
it.append(getScriptBuilderInterface());
it.append(".class).get();"); //$NON-NLS-1$
it.newLine();
it.append("\t\tbuilder.eInit(resource, packageName, context);"); //$NON-NLS-1$
it.newLine();
it.append("\t\treturn builder;"); //$NON-NLS-1$
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append("\t/** Create the factory for a " + getLanguageName() + " script."); //$NON-NLS-1$ //$NON-NLS-2$
it.newLine();
it.append("\t * <p>The resource set is provided by the context."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param packageName the name of the package of the script."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param context the context for type resolution."); //$NON-NLS-1$
it.newLine();
it.append("\t * @return the factory."); //$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("\tpublic "); //$NON-NLS-1$
it.append(getScriptBuilderInterface());
it.append(" createScript(String packageName, "); //$NON-NLS-1$
it.append(IJvmTypeProvider.class);
it.append(" context) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\treturn createScript(packageName, createResource(context.getResourceSet()), context);"); //$NON-NLS-1$
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
}
});
if (enableAppenders) {
this.builderFactoryContributions.addContribution(new StringConcatenationClient() {
@Override
protected void appendTo(TargetStringConcatenation it) {
it.append("\t/** Create the appender for a " + getLanguageName() + " script."); //$NON-NLS-1$ //$NON-NLS-2$
it.newLine();
it.append("\t * @param packageName the name of the package of the script."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param resourceSet the resource set in which the script is created."); //$NON-NLS-1$
it.newLine();
it.append("\t * @return the appender."); //$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("\tpublic "); //$NON-NLS-1$
it.append(getScriptAppender());
it.append(" buildScript(String packageName, "); //$NON-NLS-1$
it.append(ResourceSet.class);
it.append(" resourceSet) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t"); //$NON-NLS-1$
it.append(getScriptAppender());
it.append(" a = new "); //$NON-NLS-1$
it.append(getScriptAppender());
it.append("(createScript(packageName, resourceSet));"); //$NON-NLS-1$
it.newLine();
it.append("\t\tgetInjector().injectMembers(a);"); //$NON-NLS-1$
it.newLine();
it.append("\t\treturn a;"); //$NON-NLS-1$
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append("\t/** Create the appender for a " + getLanguageName() + " script."); //$NON-NLS-1$ //$NON-NLS-2$
it.newLine();
it.append("\t * @param packageName the name of the package of the script."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param resource the resource in which the script is created."); //$NON-NLS-1$
it.newLine();
it.append("\t * @return the appender."); //$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("\tpublic "); //$NON-NLS-1$
it.append(getScriptAppender());
it.append(" buildScript(String packageName, "); //$NON-NLS-1$
it.append(Resource.class);
it.append(" resource) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t"); //$NON-NLS-1$
it.append(getScriptAppender());
it.append(" a = new "); //$NON-NLS-1$
it.append(getScriptAppender());
it.append("(createScript(packageName, resource));"); //$NON-NLS-1$
it.newLine();
it.append("\t\tgetInjector().injectMembers(a);"); //$NON-NLS-1$
it.newLine();
it.append("\t\treturn a;"); //$NON-NLS-1$
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append("\t/** Create the appender for a " + getLanguageName() + " script."); //$NON-NLS-1$ //$NON-NLS-2$
it.newLine();
it.append("\t * @param packageName the name of the package of the script."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param resource the resource in which the script is created."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param context the context for type resolution."); //$NON-NLS-1$
it.newLine();
it.append("\t * @return the appender."); //$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("\tpublic "); //$NON-NLS-1$
it.append(getScriptAppender());
it.append(" buildScript(String packageName, "); //$NON-NLS-1$
it.append(Resource.class);
it.append(" resource, "); //$NON-NLS-1$
it.append(IJvmTypeProvider.class);
it.append(" context) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t"); //$NON-NLS-1$
it.append(getScriptAppender());
it.append(" a = new "); //$NON-NLS-1$
it.append(getScriptAppender());
it.append("(createScript(packageName, resource, context));"); //$NON-NLS-1$
it.newLine();
it.append("\t\tgetInjector().injectMembers(a);"); //$NON-NLS-1$
it.newLine();
it.append("\t\treturn a;"); //$NON-NLS-1$
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append("\t/** Create the appender for a " + getLanguageName() + " script."); //$NON-NLS-1$ //$NON-NLS-2$
it.newLine();
it.append("\t * <p>The resource set is provided by the context."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param packageName the name of the package of the script."); //$NON-NLS-1$
it.newLine();
it.append("\t * @param context the context for type resolution."); //$NON-NLS-1$
it.newLine();
it.append("\t * @return the appender."); //$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("\tpublic "); //$NON-NLS-1$
it.append(getScriptAppender());
it.append(" buildScript(String packageName, "); //$NON-NLS-1$
it.append(IJvmTypeProvider.class);
it.append(" context) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t"); //$NON-NLS-1$
it.append(getScriptAppender());
it.append(" a = new "); //$NON-NLS-1$
it.append(getScriptAppender());
it.append("(createScript(packageName, context));"); //$NON-NLS-1$
it.newLine();
it.append("\t\tgetInjector().injectMembers(a);"); //$NON-NLS-1$
it.newLine();
it.append("\t\treturn a;"); //$NON-NLS-1$
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
}
});
}
}
@Override
public void generateXtendStubs() {
super.generateXtendStubs();
final TypeReference stub = getScriptBuilderImplCustom();
final StringConcatenationClient content = new StringConcatenationClient() {
@Override
protected void appendTo(TargetStringConcatenation it) {
it.append("/** User-defined builder of the " + getLanguageName() + " scripts."); //$NON-NLS-1$//$NON-NLS-2$
it.newLine();
it.append(" */"); //$NON-NLS-1$
it.newLine();
it.append("class "); //$NON-NLS-1$
it.append(stub);
it.append(" extends "); //$NON-NLS-1$
it.append(getScriptBuilderImpl());
it.append(" {"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append("}"); //$NON-NLS-1$
it.newLine();
}
};
final XtendFileAccess xtendFile = getFileAccessFactory().createXtendFile(stub, content);
final IFileSystemAccess2 fileSystem = getSrc();
if (!fileSystem.isFile(xtendFile.getPath())) {
xtendFile.writeTo(fileSystem);
}
}
@Override
public void generateJavaStubs() {
super.generateJavaStubs();
final TypeReference stub = getScriptBuilderImplCustom();
final StringConcatenationClient content = new StringConcatenationClient() {
@Override
protected void appendTo(TargetStringConcatenation it) {
it.append("/** User-defined builder of the " + getLanguageName() + " scripts."); //$NON-NLS-1$//$NON-NLS-2$
it.newLine();
it.append(" */"); //$NON-NLS-1$
it.newLine();
it.append("public class "); //$NON-NLS-1$
it.append(stub);
it.append(" extends "); //$NON-NLS-1$
it.append(getScriptBuilderImpl());
it.append(" {"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append("}"); //$NON-NLS-1$
it.newLine();
}
};
final JavaFileAccess javaFile = getFileAccessFactory().createJavaFile(stub, content);
final IFileSystemAccess2 fileSystem = getSrc();
if (!fileSystem.isFile(javaFile.getPath())) {
javaFile.writeTo(fileSystem);
}
}
/** Extract a top element from the grammar.
*
* @param description the description of the top element.
* @param forInterface indicates if the generated code is for interfaces.
* @param forAppender indicates if the generated code is for appenders.
* @return the top element.
*/
@SuppressWarnings("checkstyle:all")
protected StringConcatenationClient generateTopElement(CodeElementExtractor.ElementDescription description,
boolean forInterface, boolean forAppender) {
final String topElementName = Strings.toFirstUpper(description.getName());
final TypeReference builderType = getCodeElementExtractor().getElementBuilderInterface(topElementName);
return new StringConcatenationClient() {
@Override
protected void appendTo(TargetStringConcatenation it) {
if (!forInterface && !forAppender) {
it.append("\t@"); //$NON-NLS-1$
it.append(Inject.class);
it.newLine();
it.append("\tprivate "); //$NON-NLS-1$
it.append(Provider.class);
it.append("<"); //$NON-NLS-1$
it.append(builderType);
it.append("> "); //$NON-NLS-1$
it.append(Strings.toFirstLower(topElementName));
it.append("Provider;"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
}
it.append("\t/** Create " + getAorAnArticle(topElementName) //$NON-NLS-1$
+ " "+ topElementName + " builder."); //$NON-NLS-1$//$NON-NLS-2$
it.newLine();
it.append("\t * @param name - the name of the " + topElementName + "."); //$NON-NLS-1$ //$NON-NLS-2$
it.newLine();
it.append("\t * @return the builder."); //$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(builderType);
it.append(" add"); //$NON-NLS-1$
it.append(topElementName);
it.append("(String name)"); //$NON-NLS-1$
if (forInterface) {
it.append(";"); //$NON-NLS-1$
it.newLineIfNotEmpty();
} else {
it.append(" {"); //$NON-NLS-1$
it.newLine();
if (forAppender) {
it.append("\t\t return this.builder.add"); //$NON-NLS-1$
it.append(topElementName);
it.append("(name);"); //$NON-NLS-1$
} else {
it.append("\t\t"); //$NON-NLS-1$
it.append(builderType);
it.append(" builder = this."); //$NON-NLS-1$
it.append(Strings.toFirstLower(topElementName));
it.append("Provider.get();"); //$NON-NLS-1$
it.newLine();
it.append("\t\tbuilder.eInit(getScript(), name, getTypeResolutionContext());"); //$NON-NLS-1$
it.newLine();
it.append("\t\treturn builder;"); //$NON-NLS-1$
}
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
}
it.newLine();
}
};
}
/** Extract top elements from the grammar.
*
* @param forInterface indicates if the generated code is for interfaces.
* @param forAppender indicates if the generated code is for appender.
* @return the top elements.
*/
protected List<StringConcatenationClient> generateTopElements(boolean forInterface, boolean forAppender) {
final List<StringConcatenationClient> topElements = new ArrayList<>();
for (final CodeElementExtractor.ElementDescription description : getCodeElementExtractor().getTopElements(
getGrammar(), getCodeBuilderConfig())) {
topElements.add(generateTopElement(description, forInterface, forAppender));
}
return topElements;
}
/** Generate the script builder interface.
*/
protected void generateIScriptBuilder() {
final List<StringConcatenationClient> topElements = generateTopElements(true, false);
final TypeReference builder = getScriptBuilderInterface();
final StringConcatenationClient content = new StringConcatenationClient() {
@Override
protected void appendTo(TargetStringConcatenation it) {
it.append("/** Builder of " + getLanguageName() + " scripts."); //$NON-NLS-1$ //$NON-NLS-2$
it.newLine();
it.append(" *"); //$NON-NLS-1$
it.newLine();
it.append(" * <p>This builder is provided for helping to create " //$NON-NLS-1$
+ getLanguageName()
+ " Ecore elements."); //$NON-NLS-1$
it.newLine();
it.append(" *"); //$NON-NLS-1$
it.newLine();
it.append(" * <p>Do not forget to invoke {@link #finalizeScript()} for creating imports, etc."); //$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(generateFieldsAndMethods(true, false));
for (final StringConcatenationClient element : topElements) {
it.append(element);
}
it.append("}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
}
};
final JavaFileAccess javaFile = getFileAccessFactory().createJavaFile(builder, content);
javaFile.writeTo(getSrcGen());
}
/** Generate the script appender.
*/
protected void generateScriptSourceAppender() {
final List<StringConcatenationClient> topElements = generateTopElements(false, true);
final TypeReference appender = getCodeElementExtractor().getElementAppenderImpl("Script"); //$NON-NLS-1$
final StringConcatenationClient content = new StringConcatenationClient() {
@Override
protected void appendTo(TargetStringConcatenation it) {
it.append("/** Appender of " + getLanguageName() + " scripts."); //$NON-NLS-1$ //$NON-NLS-2$
it.newLine();
it.append(" *"); //$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(getScriptAppender().getSimpleName());
it.append(" extends "); //$NON-NLS-1$
it.append(getCodeElementExtractor().getAbstractAppenderImpl());
it.append(" implements "); //$NON-NLS-1$
it.append(getScriptBuilderInterface());
it.append(" {"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append(generateFieldsAndMethods(false, true));
for (final StringConcatenationClient element : topElements) {
it.append(element);
}
it.append("}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
}
};
final JavaFileAccess javaFile = getFileAccessFactory().createJavaFile(appender, content);
javaFile.writeTo(getSrcGen());
}
/** Generate the script builder default implementation.
*/
protected void generateScriptBuilderImpl() {
final List<StringConcatenationClient> topElements = generateTopElements(false, false);
final TypeReference script = getScriptBuilderImpl();
final TypeReference scriptInterface = getScriptBuilderInterface();
final StringConcatenationClient content = new StringConcatenationClient() {
@Override
protected void appendTo(TargetStringConcatenation it) {
it.append("@SuppressWarnings(\"all\")"); //$NON-NLS-1$
it.newLine();
it.append("public class "); //$NON-NLS-1$
it.append(script.getSimpleName());
it.append(" extends "); //$NON-NLS-1$
it.append(getAbstractBuilderImpl());
it.append(" implements "); //$NON-NLS-1$
it.append(scriptInterface);
it.append(" {"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append(generateFieldsAndMethods(false, false));
for (final StringConcatenationClient element : topElements) {
it.append(element);
}
it.append("}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
}
};
final JavaFileAccess javaFile = getFileAccessFactory().createJavaFile(script, content);
javaFile.writeTo(getSrcGen());
}
/** Generate the fields and the methods.
*
* @param forInterface indicates if the generated code is for interfaces.
* @param forAppender indicates if the generated code is for appender.
* @return the fields and methods.
*/
@SuppressWarnings("checkstyle:all")
protected StringConcatenationClient generateFieldsAndMethods(boolean forInterface, boolean forAppender) {
TypeReference scriptInterface = getCodeElementExtractor().getLanguageScriptInterface();
return new StringConcatenationClient() {
@Override
protected void appendTo(TargetStringConcatenation it) {
// Fields
if (!forInterface && !forAppender) {
it.append("\tprivate "); //$NON-NLS-1$
it.append(scriptInterface);
it.append(" script;"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append("\tprivate boolean isFinalized;"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
} else if (forAppender) {
it.append("\tprivate "); //$NON-NLS-1$
it.append(getScriptBuilderInterface());
it.append(" builder;"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
}
if (forInterface || forAppender) {
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();
}
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();
}
if (forAppender) {
it.append("\tpublic "); //$NON-NLS-1$
it.append(getScriptAppender().getSimpleName());
it.append("("); //$NON-NLS-1$
it.append(getScriptBuilderInterface());
it.append(" builder) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\tthis.builder = builder;"); //$NON-NLS-1$
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
it.append("\tpublic void build("); //$NON-NLS-1$
it.append(ISourceAppender.class);
it.append(" appender) throws "); //$NON-NLS-1$
it.append(IOException.class);
it.append(" {"); //$NON-NLS-1$
it.newLine();
it.append("\t\tif (!isFinalized()) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\tfinalizeScript();"); //$NON-NLS-1$
it.newLine();
it.append("\t\t}"); //$NON-NLS-1$
it.newLine();
it.append("\t\tbuild(this.builder.getScript(), appender);"); //$NON-NLS-1$
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
}
it.append("\t/** Create the internal " + getLanguageName() + " script."); //$NON-NLS-1$ //$NON-NLS-2$
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(Resource.class);
it.append(" resource, String packageName, "); //$NON-NLS-1$
it.append(IJvmTypeProvider.class);
it.append(" context)"); //$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(resource, packageName, context);"); //$NON-NLS-1$
} else {
it.append("\t\tsetTypeResolutionContext(context);"); //$NON-NLS-1$
it.newLine();
it.append("\t\tif (this.script == null) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\tthis.script = "); //$NON-NLS-1$
it.append(getXFactoryFor(scriptInterface));
it.append(".eINSTANCE.create"); //$NON-NLS-1$
it.append(Strings.toFirstUpper(scriptInterface.getSimpleName()));
it.append("();"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t"); //$NON-NLS-1$
it.append(EList.class);
it.append("<"); //$NON-NLS-1$
it.append(EObject.class);
it.append("> content = resource.getContents();"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\tif (!content.isEmpty()) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t\tcontent.clear();"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t}"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\tcontent.add(this.script);"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\tif (!"); //$NON-NLS-1$
it.append(Strings.class);
it.append(".isEmpty(packageName)) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t\tscript.setPackage(packageName);"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t}"); //$NON-NLS-1$
it.newLine();
it.append("\t\t}"); //$NON-NLS-1$
}
it.newLine();
it.append("\t}"); //$NON-NLS-1$
}
it.newLineIfNotEmpty();
it.newLine();
it.append("\t/** Replies the " + getLanguageName() + " script."); //$NON-NLS-1$ //$NON-NLS-2$
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(scriptInterface);
it.append(" getScript()"); //$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.getScript();"); //$NON-NLS-1$
} else {
it.append("\t\treturn this.script;"); //$NON-NLS-1$
}
it.newLine();
it.append("\t}"); //$NON-NLS-1$
}
it.newLineIfNotEmpty();
it.newLine();
it.append("\t/** Replies the resource to which the script 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 getScript().eResource();"); //$NON-NLS-1$
it.newLine();
it.append("\t}"); //$NON-NLS-1$
}
it.newLineIfNotEmpty();
it.newLine();
it.append("\t/** Finalize the script."); //$NON-NLS-1$
it.newLine();
it.append("\t *"); //$NON-NLS-1$
it.newLine();
it.append("\t * <p>The finalization includes: <ul>"); //$NON-NLS-1$
it.newLine();
it.append("\t * <li>The import section is created.</li>"); //$NON-NLS-1$
it.newLine();
it.append("\t * </ul>"); //$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 finalizeScript()"); //$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.finalizeScript();"); //$NON-NLS-1$
} else {
it.append("\t\tif (this.isFinalized) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\tthrow new "); //$NON-NLS-1$
it.append(IllegalStateException.class);
it.append("(\"already finalized\");"); //$NON-NLS-1$
it.newLine();
it.append("\t\t}"); //$NON-NLS-1$
it.newLine();
it.append("\t\tthis.isFinalized = true;"); //$NON-NLS-1$
it.newLine();
it.append("\t\t"); //$NON-NLS-1$
it.append(ImportManager.class);
it.append(" concreteImports = new "); //$NON-NLS-1$
it.append(ImportManager.class);
it.append("(true);"); //$NON-NLS-1$
it.newLine();
it.append("\t\t"); //$NON-NLS-1$
it.append(XImportSection.class);
it.append(" importSection = getScript().getImportSection();"); //$NON-NLS-1$
it.newLine();
it.append("\t\tif (importSection != null) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\tfor ("); //$NON-NLS-1$
it.append(XImportDeclaration.class);
it.append(" decl : importSection.getImportDeclarations()) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t\tconcreteImports.addImportFor(decl.getImportedType());"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t}"); //$NON-NLS-1$
it.newLine();
it.append("\t\t}"); //$NON-NLS-1$
it.newLine();
it.append("\t\tfor (String importName : getImportManager().getImports()) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t"); //$NON-NLS-1$
it.append(JvmType.class);
it.append(" type = findType(getScript(), importName).getType();"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\tif (concreteImports.addImportFor(type) && type instanceof "); //$NON-NLS-1$
it.append(JvmDeclaredType.class);
it.append(") {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t\t"); //$NON-NLS-1$
it.append(XImportDeclaration.class);
it.append(" declaration = "); //$NON-NLS-1$
it.append(XtypeFactory.class);
it.append(".eINSTANCE.createXImportDeclaration();"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t\tdeclaration.setImportedType(("); //$NON-NLS-1$
it.append(JvmDeclaredType.class);
it.append(") type);"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t\tif (importSection == null) {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t\t\timportSection = "); //$NON-NLS-1$
it.append(XtypeFactory.class);
it.append(".eINSTANCE.createXImportSection();"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t\t\tgetScript().setImportSection(importSection);"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t\t}"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t\timportSection.getImportDeclarations().add(declaration);"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t}"); //$NON-NLS-1$
it.newLine();
it.append("\t\t}"); //$NON-NLS-1$
it.newLine();
it.append("\t\t"); //$NON-NLS-1$
it.append(Resource.class);
it.append(" resource = getScript().eResource();"); //$NON-NLS-1$
it.newLine();
it.append("\t\tif (resource instanceof "); //$NON-NLS-1$
it.append(DerivedStateAwareResource.class);
it.append(") {"); //$NON-NLS-1$
it.newLine();
it.append("\t\t\t(("); //$NON-NLS-1$
it.append(DerivedStateAwareResource.class);
it.append(") resource).discardDerivedState();"); //$NON-NLS-1$
it.newLine();
it.append("\t\t}"); //$NON-NLS-1$
}
it.newLine();
it.append("\t}"); //$NON-NLS-1$
}
it.newLineIfNotEmpty();
it.newLine();
it.append("\t/** Replies if the script was finalized."); //$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("boolean isFinalized()"); //$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.isFinalized();"); //$NON-NLS-1$
} else {
it.append("\t\treturn this.isFinalized;"); //$NON-NLS-1$
}
it.newLine();
it.append("\t}"); //$NON-NLS-1$
}
it.newLineIfNotEmpty();
it.newLine();
if (!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(this.script);"); //$NON-NLS-1$
}
it.newLine();
it.append("\t}"); //$NON-NLS-1$
it.newLineIfNotEmpty();
it.newLine();
}
}
};
}
}