package org.overture.codegen.vdm2jml;
import java.util.LinkedList;
import java.util.List;
import org.apache.log4j.Logger;
import org.overture.ast.util.ClonableString;
import org.overture.codegen.ir.IRConstants;
import org.overture.codegen.ir.IRStatus;
import org.overture.codegen.ir.PIR;
import org.overture.codegen.ir.SDeclIR;
import org.overture.codegen.ir.declarations.ADefaultClassDeclIR;
import org.overture.codegen.ir.declarations.AFieldDeclIR;
import org.overture.codegen.ir.declarations.AMethodDeclIR;
import org.overture.codegen.ir.declarations.ARecordDeclIR;
import org.overture.codegen.vdm2java.JavaCodeGenUtil;
public class JmlAnnotationHelper
{
private JmlGenerator jmlGen;
private Logger log = Logger.getLogger(this.getClass().getName());
public JmlAnnotationHelper(JmlGenerator jmlGen)
{
this.jmlGen = jmlGen;
}
public void makeNullableByDefault(ADefaultClassDeclIR clazz)
{
clazz.setGlobalMetaData(consMetaData(JmlGenerator.JML_NULLABLE_BY_DEFAULT));
}
public void makeNamedTypeInvFuncsPublic(ADefaultClassDeclIR clazz)
{
List<AMethodDeclIR> nameInvMethods = jmlGen.getUtil().getNamedTypeInvMethods(clazz);
for (AMethodDeclIR method : nameInvMethods)
{
makeCondPublic(method);
}
}
public void makeRecMethodsPure(List<IRStatus<PIR>> ast)
{
List<ARecordDeclIR> records = jmlGen.getUtil().getRecords(ast);
for (ARecordDeclIR rec : records)
{
for (AMethodDeclIR method : rec.getMethods())
{
if (!method.getIsConstructor())
{
makePure(method);
}
}
}
}
public List<ClonableString> consAnno(String jmlAnno, String pred,
List<String> fieldNames)
{
StringBuilder sb = new StringBuilder();
sb.append(String.format("//@ %s %s", jmlAnno, pred));
appendFieldNames(fieldNames, sb);
return consMetaData(sb);
}
private void appendFieldNames(List<String> fieldNames, StringBuilder sb)
{
sb.append("(");
String sep = "";
for (String fName : fieldNames)
{
sb.append(sep).append(fName);
sep = ",";
}
sb.append(");");
}
public void addInvCheckGhostVarDecl(ADefaultClassDeclIR owner)
{
String metaStr = String.format(JmlGenerator.JML_INV_CHECKS_ON_DECL, JmlGenerator.INV_CHECKS_ON_GHOST_VAR_NAME);
appendMetaData(owner, consMetaData(metaStr));
}
private String consInvChecksOnName(ADefaultClassDeclIR owner)
{
StringBuilder prefix = new StringBuilder();
if (JavaCodeGenUtil.isValidJavaPackage(owner.getPackage()))
{
prefix.append(owner.getPackage());
prefix.append(".");
}
prefix.append(owner.getName());
prefix.append(".");
prefix.append(JmlGenerator.INV_CHECKS_ON_GHOST_VAR_NAME);
return prefix.toString();
}
public void addRecInv(ARecordDeclIR r)
{
List<String> args = jmlGen.getUtil().getRecFieldNames(r);
String jmlAnno = "public " + JmlGenerator.JML_INSTANCE_INV_ANNOTATION;
StringBuilder pred = new StringBuilder();
pred.append(consInvChecksOnNameEncClass());
pred.append(JmlGenerator.JML_IMPLIES);
pred.append(JmlGenerator.INV_PREFIX);
pred.append(r.getName());
appendMetaData(r, consAnno(jmlAnno, pred.toString(), args));
}
public String consInvChecksOnNameEncClass()
{
return consInvChecksOnNameEncClass(null);
}
public String consInvChecksOnNameEncClass(
ADefaultClassDeclIR enclosingClass)
{
if (enclosingClass != null
&& enclosingClass == jmlGen.getInvChecksFlagOwner())
{
return JmlGenerator.INV_CHECKS_ON_GHOST_VAR_NAME;
} else
{
return consInvChecksOnName(jmlGen.getInvChecksFlagOwner());
}
}
public void makePure(SDeclIR cond)
{
if (cond != null)
{
appendMetaData(cond, consMetaData(JmlGenerator.JML_PURE));
}
}
public void makeHelper(SDeclIR cond)
{
if (cond != null)
{
appendMetaData(cond, consMetaData(JmlGenerator.JML_HELPER));
}
}
public void makeCondPublic(SDeclIR cond)
{
if (cond instanceof AMethodDeclIR)
{
((AMethodDeclIR) cond).setAccess(IRConstants.PUBLIC);
} else
{
log.error("Expected method declaration but got: " + cond);
}
}
public void addMetaData(PIR node, List<ClonableString> extraMetaData,
boolean prepend)
{
this.jmlGen.getJavaGen().getInfo().getNodeAssistant().addMetaData(node, extraMetaData, prepend);
}
public void appendMetaData(PIR node, List<ClonableString> extraMetaData)
{
addMetaData(node, extraMetaData, false);
}
public void makeSpecPublic(AFieldDeclIR f)
{
appendMetaData(f, consMetaData(JmlGenerator.JML_SPEC_PUBLIC));
}
public List<ClonableString> consMetaData(StringBuilder sb)
{
return consMetaData(sb.toString());
}
public List<ClonableString> consMetaData(String str)
{
List<ClonableString> inv = new LinkedList<ClonableString>();
inv.add(new ClonableString(str));
return inv;
}
}