/**
* Copyright (c) 2009-2011, The HATS Consortium. All rights reserved.
* This file is licensed under the terms of the Modified BSD License.
*/
package abs.backend.java.codegeneration.dynamic;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import abs.backend.java.JavaBackend;
import abs.backend.java.codegeneration.JavaCodeGenerationException;
import abs.backend.java.codegeneration.JavaCodeStream;
import abs.backend.java.codegeneration.JavaGeneratorHelper;
import abs.backend.java.JavaBackendConstants;
import abs.backend.java.codegeneration.JavaCode;
import abs.backend.java.lib.runtime.ABSBuiltInFunctions;
import abs.backend.java.lib.runtime.ABSClosure;
import abs.backend.java.lib.runtime.ABSDynamicClass;
import abs.backend.java.lib.runtime.ABSDynamicDelta;
import abs.backend.java.lib.runtime.ABSDynamicObject;
import abs.backend.java.lib.runtime.ABSDynamicProduct;
import abs.backend.java.lib.runtime.ABSDynamicReconfiguration;
import abs.backend.java.lib.runtime.ABSDynamicRuntime;
import abs.backend.java.lib.runtime.ABSDynamicUpdate;
import abs.backend.java.lib.runtime.ABSField;
import abs.backend.java.lib.runtime.ABSFut;
import abs.backend.java.lib.runtime.ABSRuntime;
import abs.backend.java.lib.runtime.AbstractAsyncCall;
import abs.backend.java.lib.runtime.Task;
import abs.backend.java.lib.types.ABSBool;
import abs.backend.java.lib.types.ABSValue;
import abs.frontend.ast.*;
import abs.frontend.typechecker.Type;
public class DynamicJavaGeneratorHelper {
private static final String FLI_METHOD_PREFIX = "fli_";
public static void generateHelpLine(ASTNode<?> node, PrintStream stream) {
JavaGeneratorHelper.generateHelpLine(node, stream);
}
public static void generateArgs(PrintStream stream, List<PureExp> args, java.util.List<Type> types) {
generateArgs(stream, null, args, types);
}
public static void generateArgs(PrintStream stream, String firstArg, List<PureExp> args, java.util.List<Type> types) {
stream.print("(");
boolean first = true;
if (firstArg != null) {
stream.print(firstArg);
first = false;
}
for (int i = 0; i < args.getNumChild(); i++) {
PureExp e = args.getChild(i);
if (!first)
stream.print(", ");
e.generateJavaDynamic(stream);
if (types.get(i).isIntType() && e.getType().isRatType())
stream.print(".truncate()");
first = false;
}
stream.print(")");
}
public static void generateParamArgs(PrintStream stream, List<ParamDecl> params) {
generateParamArgs(stream, null, params);
}
public static void generateParamArgs(PrintStream stream, String firstArg, List<ParamDecl> params) {
stream.print("(");
boolean first = true;
if (firstArg != null) {
stream.print(firstArg);
first = false;
}
for (ParamDecl d : params) {
if (!first)
stream.print(", ");
stream.print(JavaBackend.getVariableName(d.getName()));
first = false;
}
stream.print(")");
}
public static void generateParams(PrintStream stream, List<ParamDecl> params) {
generateParams(stream, null, params);
}
public static void generateParams(PrintStream stream, String firstArg, List<ParamDecl> params) {
stream.print("(");
boolean first = true;
if (firstArg != null) {
stream.print(firstArg);
first = false;
}
for (ParamDecl d : params) {
if (!first)
stream.print(", ");
// stream.print("final ");
d.generateJavaDynamic(stream);
first = false;
}
stream.print(")");
}
public static void generateTypeParameters(PrintStream stream, Decl dtd, boolean plusExtends) {
List<TypeParameterDecl> typeParams = null;
if (dtd instanceof HasTypeParameters) {
typeParams = ((HasTypeParameters)dtd).getTypeParameters();
} else
return;
if (typeParams.getNumChild() > 0) {
stream.print("<");
boolean isFirst = true;
for (TypeParameterDecl d : typeParams) {
if (isFirst)
isFirst = false;
else
stream.print(", ");
stream.print(d.getName());
if (plusExtends)
stream.print(" extends " + ABSValue.class.getName());
}
stream.print(">");
}
}
public static void generateBuiltInFnApp(PrintStream stream, FnApp app) {
FunctionDecl d = (FunctionDecl) app.getDecl();
String name = d.getName();
stream.print(ABSBuiltInFunctions.class.getName() + "." + name);
generateArgs(stream, app.getParams(), app.getTypesFromExp());
}
public static String getDebugString(Stmt stmt) {
return getDebugString(stmt, stmt.getStartLine());
}
public static String getDebugString(Stmt stmt, int line) {
String fileName = stmt.getCompilationUnit().getFileName().replace("\\", "\\\\");
return "if (thisP.__ABS_getRuntime().debuggingEnabled()) thisP.__ABS_getRuntime().nextStep(\""
+ fileName + "\"," + line + ");";
}
public static void generateMethodSig(PrintStream stream, MethodSig sig, boolean async) {
generateMethodSig(stream, sig, async, "", "");
}
public static void generateMethodSig(PrintStream stream, MethodSig sig, boolean async, String modifier, String prefix) {
DynamicJavaGeneratorHelper.generateHelpLine(sig,stream);
stream.print("public " + modifier + " ");
if (async) {
prefix = "async_";
stream.print(ABSFut.class.getName()+"<");
}
sig.getReturnType().generateJavaDynamic(stream);
if (async)
stream.print(">");
stream.print(" " + prefix + JavaBackend.getMethodName(sig.getName()));
DynamicJavaGeneratorHelper.generateParams(stream, sig.getParams());
}
public static void generateAsyncMethod(PrintStream stream, MethodImpl method) {
final MethodSig sig = method.getMethodSig();
generateMethodSig(stream, sig, true, "final","");
stream.println("{");
stream.println("return (" + ABSFut.class.getName() + ")");
generateAsyncCall(stream, "this", null, method.getContextDecl().getType(), null, sig.getParams(),
sig.getTypes(),sig.getName());
stream.println(";");
stream.println("}");
}
public static void generateAsyncCall(PrintStream stream, AsyncCall call) {
final PureExp callee = call.getCallee();
final List<PureExp> params = call.getParams();
final String method = call.getMethod();
generateAsyncCall(stream, null, callee, callee.getType(), params, null,
call.getTypesFromExp(), method);
}
private static void generateAsyncCall(PrintStream stream, final String calleeString,
final PureExp callee, final Type calleeType, final List<PureExp> args,
final List<ParamDecl> params,
final java.util.List<Type> paramTypes,
final String method)
{
stream.print(ABSRuntime.class.getName() + ".getCurrentRuntime().asyncCall(");
stream.print("new " + AbstractAsyncCall.class.getName() + "<" + ABSDynamicObject.class.getName() + ">(thisP, ");
stream.print("(" + ABSDynamicObject.class.getName() + ")" + ABSRuntime.class.getName() + ".checkForNull(");
if (calleeString != null)
stream.print(calleeString);
else
callee.generateJavaDynamic(stream);
stream.println(")) {");
for (int i = 0; i < paramTypes.size(); i++) {
stream.print(ABSValue.class.getName()+" arg" + i + ";");
}
generateTaskGetArgsMethod(stream, paramTypes.size());
generateTaskInitMethod(stream, paramTypes);
stream.println("public java.lang.String methodName() { return \"" + method + "\"; }");
stream.print("public Object execute() {");
stream.print(" return ((" + ABSDynamicObject.class.getName() + ")target).dispatch(");
generateArgStringList(stream, "\"" + method + "\"", paramTypes.size());
stream.println("); }");
stream.print("}.init");
if (args != null)
DynamicJavaGeneratorHelper.generateArgs(stream,args, paramTypes);
else
DynamicJavaGeneratorHelper.generateParamArgs(stream, params);
stream.print(")");
}
public static void generateAwaitAsyncCall(PrintStream stream, AwaitAsyncCall call) {
final PureExp callee = call.getCallee();
final List<PureExp> params = call.getParams();
final String method = call.getMethod();
// FIXME: implement await, assign after async call
generateAsyncCall(stream, null, callee, callee.getType(), params, null,
call.getTypesFromExp(), method);
}
public static void generateSyncCall(PrintStream stream, SyncCall call) {
stream.print("((" + ABSDynamicObject.class.getName() + ")" + ABSRuntime.class.getName() + ".checkForNull(");
call.getCallee().generateJavaDynamic(stream);
stream.print("))");
stream.print(".dispatch");
DynamicJavaGeneratorHelper.generateArgs(stream, "\"" + call.getMethod() + "\"", call.getParams(), call.getTypesFromExp());
}
private static void generateTaskInitMethod(PrintStream stream, final java.util.List<Type> paramTypes) {
stream.print("public " + abs.backend.java.lib.runtime.AsyncCall.class.getName() + "<?> init(");
for (int i = 0; i < paramTypes.size(); i++) {
if (i > 0) stream.print(", ");
stream.print(ABSValue.class.getName() + " _arg" + i);
}
stream.print(") {");
for (int i = 0; i < paramTypes.size(); i++) {
stream.print("arg" + i + " = _arg" + i + ";");
}
stream.println(" return this; }");
}
private static void generateTaskGetArgsMethod(PrintStream stream, final int n) {
stream.println("public java.util.List<" + ABSValue.class.getName() + "> getArgs() {");
stream.println("return java.util.Arrays.asList(new " + ABSValue.class.getName() + "[] {");
generateArgStringList(stream, n);
stream.println("});");
stream.println("}");
}
private static void generateArgStringList(PrintStream stream, String init, final int n) {
stream.print(init);
for (int i = 0; i < n; i++) {
stream.print(",");
stream.print("arg" + i);
}
}
private static void generateArgStringList(PrintStream stream, final int n) {
for (int i = 0; i < n; i++) {
if (i > 0) stream.print(",");
stream.print("arg" + i);
}
}
public static void generateClassDecl(PrintStream stream, final ClassDecl decl) {
// if (decl.isForeign()) {
// // generate standard code
// new abs.backend.java.codegeneration.ClassDeclGenerator("", stream, decl).generate();
// } else {
// generate dynamic/untyped code
new ClassDeclGenerator(stream, decl).generate();
// }
}
public static void generateMethodImpl(PrintStream stream, final MethodImpl m) {
// methods are mapped to static inner classes
DynamicJavaGeneratorHelper.generateHelpLine(m, stream);
stream.println("public static class " + m.getMethodSig().getName() + " extends " + ABSClosure.class.getName() + " {");
stream.println("private static " + ABSClosure.class.getName() + " instance;");
stream.println("public static " + ABSClosure.class.getName() + " singleton() {");
stream.println("if (instance == null) { instance = new " + m.getMethodSig().getName() + "(); }");
stream.println("return instance;");
stream.println("}");
stream.println("public " + ABSValue.class.getName() + " exec(final " + ABSDynamicObject.class.getName() + " thisP, " + ABSValue.class.getName() + "... args) {");
for (int i = 0; i < m.getMethodSig().getNumParam(); i++) {
ParamDecl d = m.getMethodSig().getParam(i);
d.generateJavaDynamic(stream);
stream.print(" = ");
if (!d.getAccess().getType().isReferenceType()) {
stream.print("(");
d.getAccess().generateJavaDynamic(stream);
stream.print(")");
}
stream.println("args[" + i + "];");
}
if (m.isForeign()) {
stream.println("// TODO call " + FLI_METHOD_PREFIX + JavaBackend.getMethodName(m.getMethodSig().getName()) + " in outer class");
} else {
generateMethodBody(stream, m, false);
}
stream.println("}");
stream.println("}");
}
public static void generateField(PrintStream stream, final FieldDecl f) {
// fields are mapped to subclasses of ABSField (because they need to store an initialisation routine)
String name = JavaBackend.getVariableName("field$" + f.getName());
DynamicJavaGeneratorHelper.generateHelpLine(f, stream);
stream.println("public static class " + name + " extends " + ABSField.class.getName() + " {");
stream.println("private static " + ABSField.class.getName() + " instance;");
stream.println("public static " + ABSField.class.getName() + " singleton() {");
stream.println("if (instance == null) { instance = new " + name + "(); }");
stream.println("return instance;");
stream.println("}");
stream.println("public " + ABSValue.class.getName() + " init(final " + ABSDynamicObject.class.getName() + " thisP " + ") {");
stream.print("return ");
if (f.hasInitExp()) {
f.getInitExp().generateJavaDynamic(stream);
} else {
stream.print("null");
}
stream.println(";");
stream.println("}");
stream.println("}");
}
public static void fieldUse(PrintStream stream, VarOrFieldUse f) {
stream.print("(");
if (! f.getType().isReferenceType()) {
stream.print("(" + JavaBackend.getQualifiedString(f.getType()) + ")");
}
stream.print("thisP.getFieldValue_Internal(\"" + f.getName() + "\"))");
}
private static void generateMethodBody(PrintStream stream, final MethodImpl m, boolean isFliMethod) {
boolean addReturn = false;
if (m.getMethodSig().getReturnType().getType().isUnitType()) {
if (m.getBlock().getNumStmt() == 0 ||
(! (m.getBlock().getStmt(m.getBlock().getNumStmt() - 1) instanceof ReturnStmt))) {
addReturn = true;
}
}
stream.println("{");
stream.println("thisP.__ABS_checkSameCOG();");
if (!isFliMethod && m.isForeign()) {
// FIXME
// stream.print("return this.");
// stream.print(FLI_METHOD_PREFIX + JavaBackend.getMethodName(m.getMethodSig().getName()));
// DynamicJavaGeneratorHelper.generateParamArgs(stream, m.getMethodSig().getParams());
// stream.println(";");
} else {
stream.println("if (thisP.__ABS_getRuntime().debuggingEnabled()) {");
stream.println(Task.class.getName() + "<?> __ABS_currentTask = thisP.__ABS_getRuntime().getCurrentTask();");
stream.println("__ABS_currentTask.newStackFrame(thisP, \"" + m.getMethodSig().getName() + "\");");
for (ParamDecl d : m.getMethodSig().getParams()) {
stream.print("__ABS_currentTask.setLocalVariable(");
stream.println("\"" + d.getName() + "\", " + d.getName() + ");");
}
stream.println("}");
m.getBlock().generateJavaDynamic(stream, addReturn);
}
stream.println("}");
}
public static void generateFLIMethod(PrintStream stream, MethodImpl m) {
// JavaGeneratorHelper.generateMethodSig("", stream, m.getMethodSig(), false, "", FLI_METHOD_PREFIX);
// Generate method signature
MethodSig sig = m.getMethodSig();
DynamicJavaGeneratorHelper.generateHelpLine(sig, stream);
stream.print("public ");
sig.getReturnType().generateJavaDynamic(stream);
stream.print(" " + FLI_METHOD_PREFIX + JavaBackend.getMethodName(sig.getName()));
DynamicJavaGeneratorHelper.generateParams(stream, sig.getParams());
// TODO now generate method body
// JavaGeneratorHelper.generateMethodBody("", stream, m, true);
stream.println(" {");
stream.println("// TODO generate body");
stream.println("}");
}
/**
* removes the gen folder and all its contents
* @param code
*/
public static void cleanGenFolder(JavaCode code) {
JavaGeneratorHelper.cleanGenFolder(code);
}
public static void printEscapedString(PrintStream stream, String content) {
JavaGeneratorHelper.printEscapedString(stream, content);
}
public static void generateExprGuard(ExpGuard expGuard, PrintStream beforeAwaitStream, PrintStream stream) {
PureExp expr = expGuard.getPureExp();
replaceLocalVariables(expr.copy(), beforeAwaitStream);
stream.print("new "+JavaBackendConstants.EXPGUARD+"() { public "+ABSBool.class.getName()+" evaluateExp() { return ");
expGuard.getPureExp().generateJavaDynamic(stream);
stream.print("; }}");
}
/**
* replace all uses of local variables and parameters by a use of a newly introduced
* temporary final local variable
*/
private static void replaceLocalVariables(ASTNode<?> astNode, PrintStream beforeAwaitStream) {
if (isLocalVarUse(astNode)) {
VarUse v = (VarUse) astNode;
replaceVarUse(beforeAwaitStream, v, (TypedVarOrFieldDecl) v.getDecl());
} else {
// process children:
for (int i=0; i < astNode.getNumChild(); i++) {
ASTNode<?> child = astNode.getChild(i);
replaceLocalVariables(child, beforeAwaitStream);
}
}
}
/***
* checks if astNode is a use of a local variable or parameter
*/
private static boolean isLocalVarUse(ASTNode<?> astNode) {
if (astNode instanceof VarUse) {
VarUse v = (VarUse) astNode;
VarOrFieldDecl decl = v.getDecl();
if (decl instanceof VarDecl || decl instanceof ParamDecl) {
return !(decl.getParent() instanceof LetExp);
}
}
return false;
}
private static long tempCounter = 0;
/**
* replaces a varUse v of the local variable vDecl by a new temporary variable, which will be
* written to beforeAwaitStream
*/
private static void replaceVarUse(PrintStream beforeAwaitStream, VarUse v, TypedVarOrFieldDecl vDecl) {
String name = JavaBackend.getVariableName(vDecl.getName());
String tempName = "temp$" + tempCounter + "$" + name;
tempCounter = Math.max(tempCounter + 1, 0);
// copy value of variable to temporary, final variable
beforeAwaitStream.print("final ");
vDecl.getAccess().generateJavaDynamic(beforeAwaitStream);
beforeAwaitStream.print(" " + tempName + " = " + name + ";");
// replace variable name with name of temporary variable
v.setName(tempName);
}
public static void generateAwaitStmt(AwaitStmt awaitStmt, PrintStream stream) {
OutputStream exprOStream = new ByteArrayOutputStream();
try {
PrintStream exprStream = new JavaCodeStream(exprOStream);
// Necessary temporary variables are written to "stream" and the
// await-expression is written to exprStream
awaitStmt.getGuard().generateJavaGuardDynamic(stream, exprStream);
stream.print(JavaBackendConstants.ABSRUNTIME + ".await(");
stream.print(exprOStream.toString());
stream.println(");");
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException(e);
}
}
public static void assign(PrintStream stream, AssignStmt assign) {
VarOrFieldUse vfu = assign.getVar();
boolean truncateNeeded
= vfu.getType().isIntType() && assign.getValue().getType().isRatType();
boolean castNeeded = !assign.getVar().getType().isReferenceType();
if (vfu instanceof FieldUse) {
stream.print("thisP.setFieldValue(\"" + vfu.getName() + "\", ");
if (truncateNeeded) stream.print("(");
assign.getValue().generateJavaDynamic(stream);
if (truncateNeeded) stream.print(").truncate()");
stream.println(");");
} else {
vfu.generateJavaDynamic(stream);
stream.print(" = ");
if (truncateNeeded) stream.print("(");
if (castNeeded) {
// cast ABSValue to more specific type
stream.print("(");
stream.print(JavaBackend.getQualifiedString(assign.getVar().getType()));
stream.print(")(");
}
assign.getValue().generateJavaDynamic(stream);
if (castNeeded) {
stream.print(")");
}
if (truncateNeeded) {
stream.print(").truncate()");
}
stream.println(";");
}
if (assign.getVar() instanceof VarUse) {
stream.print("if (thisP.__ABS_getRuntime().debuggingEnabled()) ");
stream.print("thisP.__ABS_getRuntime().getCurrentTask().setLocalVariable(\"" + assign.getVar().getName() + "\", ");
assign.getVar().generateJavaDynamic(stream);
stream.println(");");
}
}
public static String generateUserSchedulingStrategy(NewExp e, PureExp exp) {
// TODO
return null;
}
public static void generateDelta(DeltaDecl delta, JavaCode.Package pkg, ArrayList<String> classes)
throws IOException, JavaCodeGenerationException {
PrintStream stream = null;
String className = JavaBackend.getDeltaName(delta.getName());
try {
File file = pkg.createJavaFile(className);
stream = new JavaCodeStream(new BufferedOutputStream(new FileOutputStream(file)));
stream.println("package " + pkg.packageName + ";");
stream.println("public class " + className + " {");
stream.println("private static " + ABSDynamicDelta.class.getName() + " instance;");
stream.println("public static " + ABSDynamicDelta.class.getName() + " singleton() {");
stream.println("if (instance == null) {");
stream.println("instance = new " + ABSDynamicDelta.class.getName() + "();");
stream.println("instance.setName(\"" + delta.getName() + "\");");
stream.println("}");
stream.println("return instance;");
stream.println("}");
//static apply method
stream.println("public static void apply(" + ABSDynamicRuntime.class.getName() + " runtime) {");
for (String cls : classes) {
stream.println(cls + ".apply();");
}
stream.println("}");
stream.println("}");
} finally {
if (stream != null)
stream.close();
}
}
public static void generateUpdate(PrintStream stream, UpdateDecl update, String className, ArrayList<String> classes) {
stream.println("private static " + ABSDynamicUpdate.class.getName() + " instance;");
stream.println("public static " + ABSDynamicUpdate.class.getName() + " singleton() {");
stream.println("if (instance == null) {");
stream.println("instance = new " + ABSDynamicUpdate.class.getName() + "();");
stream.println("instance.setName(\"" + update.getName() + "\");");
stream.println("}");
stream.println("return instance;");
stream.println("}");
// override apply method
stream.println("public static void apply(" + ABSDynamicRuntime.class.getName() + " runtime) {");
for (ObjectUpdate ou :update.getObjectUpdates()) {
stream.println("{");
stream.println("// Call apply() for to update objects of class " + ou.getClassName());
stream.println(ABSDynamicClass.class.getName() + " cls = " + JavaBackend.getClassName(ou.getClassName()) + ".singleton();");
stream.println("for (" + ABSDynamicObject.class.getName() + " obj : runtime.getAllObjects(cls)) {");
stream.println("// exec update...");
stream.println("System.out.println(obj.toString());");
stream.println("}");
stream.println("}");
}
stream.println("}");
for (ObjectUpdate ou :update.getObjectUpdates()) {
generateObjectUpdate(stream, ou);
}
}
public static void generateObjectUpdate(PrintStream stream, ObjectUpdate ou) {
// object updates are mapped to static inner classes
DynamicJavaGeneratorHelper.generateHelpLine(ou, stream);
// stream.println("public static class " + ou.getClassName() + " extends " + ABSClosure.class.getName() + " {");
// stream.println("public " + ABSValue.class.getName() + " exec(final " + ABSDynamicObject.class.getName() + " thisP, " + ABSValue.class.getName() + "... args) {");
// generate body
// FIXME Var resolution
// ou.getAwaitStmt().generateJavaDynamic(stream);
// for (VarDeclStmt stmt : ou.getUpdatePreamble().getVarDeclStmts())
// stmt.generateJavaDynamic(stream);
// for (AssignStmt stmt : ou.getPreBodyList())
// stmt.generateJavaDynamic(stream);
// for (AssignStmt stmt : ou.getPostBodyList())
// stmt.generateJavaDynamic(stream);
// stream.println("}");
// stream.println("}");
}
public static void generateProduct(PrintStream stream, ProductDecl prod, HashMap<String, ProductDecl> allProducts) {
stream.println("private static " + ABSDynamicProduct.class.getName() + " instance;");
stream.println("public static " + ABSDynamicProduct.class.getName() + " singleton() {");
stream.println("if (instance == null) {");
stream.println("instance = new " + ABSDynamicProduct.class.getName() + "();");
stream.println("instance.setName(\"" + prod.getName() + "\");");
// Features (just names, currently not used)
for (Feature feature : prod.getProduct().getFeatures())
stream.println("instance.addFeature(\"" + feature.getName() + "\");");
// Reconfigurations
for (Reconfiguration recf : prod.getReconfigurations()) {
stream.println("instance.addReconfiguration("
+ JavaBackendConstants.LIB_RDM_PACKAGE + "."
+ JavaBackend.getProductName(recf.getTargetProductID()) + ".singleton()"
+ ", "
+ JavaBackendConstants.LIB_RDM_PACKAGE + "."
+ JavaBackend.getReconfigurationName(prod.getName(), recf.getTargetProductID()) + ".singleton());");
}
stream.println("}");
stream.println("return instance;");
stream.println("}");
}
public static void generateReconfiguration(PrintStream stream, Reconfiguration recf, ProductDecl currentP, HashMap<String, ProductDecl> allProducts) {
stream.println("private static " + ABSDynamicReconfiguration.class.getName() + " instance;");
stream.println("public static " + ABSDynamicReconfiguration.class.getName() + " singleton() {");
stream.println("if (instance == null) {");
stream.println("instance = new " + ABSDynamicReconfiguration.class.getName() + "();");
stream.println("instance.setName(\"" + currentP.getName() + "->" + recf.getTargetProductID() + "\");");
// Current and Target products
stream.println("instance.setCurrentProduct(" + JavaBackendConstants.LIB_RDM_PACKAGE + "."
+ JavaBackend.getProductName(currentP.getName()) + ".singleton());");
stream.println("instance.setTargetProduct(" + JavaBackendConstants.LIB_RDM_PACKAGE + "."
+ JavaBackend.getProductName(recf.getTargetProductID()) + ".singleton());");
// StateUpdate
stream.println("instance.setUpdate(" + JavaBackendConstants.LIB_UPDATES_PACKAGE + "."
+ JavaBackend.getUpdateName(recf.getUpdateID()) + ".singleton());");
// Deltas
List<DeltaID> deltaIDs = recf.getDeltaIDs();
stream.print("instance.setDeltas(");
if (deltaIDs.getNumChild() == 0) { // no deltas
stream.print(Collections.class.getName() + ".<" + ABSDynamicDelta.class.getName() + ">emptyList()");
} else {
StringBuilder deltaList = new StringBuilder();
deltaList.append(Arrays.class.getName() + ".asList(");
boolean first = true;
for (DeltaID did : deltaIDs) {
if (first) first = false;
else deltaList.append(", ");
deltaList.append(JavaBackend.getDeltaPackageName(did.getName()) + "."
+ JavaBackend.getDeltaName(did.getName()) + ".singleton()");
}
deltaList.append(")");
stream.print(deltaList);
}
stream.println(");");
stream.println("}");
stream.println("return instance;");
stream.println("}");
}
}