package xapi.dev.components; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import xapi.dev.ui.ContainerMetadata; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import static com.github.javaparser.ASTHelper.extractAttrValue; import static com.github.javaparser.ASTHelper.extractStringValue; /** * @author James X. Nelson (james@wetheinter.net) * Created on 5/29/16. */ public class MethodReferenceReplacementVisitor extends VoidVisitorAdapter<ContainerMetadata> { protected static final AtomicInteger random = new AtomicInteger(); public static MethodReferenceReplacementVisitor mutateExpression(UiContainerExpr container, ContainerMetadata metadata) { MethodReferenceReplacementVisitor visitor = new MethodReferenceReplacementVisitor(); container.accept(visitor, metadata); return visitor; } private UiContainerExpr container; private UiAttrExpr attr; @Override public void visit( UiContainerExpr n, ContainerMetadata arg ) { final UiContainerExpr oldContainer = container; container = n; super.visit(n, arg); container = oldContainer; } @Override public void visit( UiAttrExpr n, ContainerMetadata arg ) { final UiAttrExpr oldAttr = attr; attr = n; super.visit(n, arg); attr = oldAttr; } @Override public void visit( MethodReferenceExpr n, ContainerMetadata arg ) { container.removeAttribute(attr); final Optional<UiAttrExpr> idAttr = container.getAttribute("id"); String ident; if (idAttr.isPresent()) { ident = extractAttrValue(idAttr.get()); } else { ident = "gen"+Integer.toString(random.incrementAndGet(), 32); container.addAttribute(true, new UiAttrExpr( new NameExpr("id"), false, new StringLiteralExpr(ident) )); } // Now, knowing the ident, we can add a modifier to find and wire up our reference at runtime. // for now, we're going to hack in only event handlers... String attrName = attr.getNameString(); if (attrName.startsWith("on")) { attrName = attrName.substring(2); } String elementType = arg.getElementTypeImported(); String name = attrName.toLowerCase(); String scopedName = extractStringValue(n.getScope()); boolean isThis = scopedName.equals("this"); boolean is$This = scopedName.equals("$this"); if (is$This) { arg.ensure$this(); } arg.addModifier(ele -> elementType + " " + ident + " = " + ele + ".querySelector(\"#" + ident + "\");" ); arg.addModifier(ele -> ident + ".addEventListener(\"" + name + "\"," ); if (is$This) { arg.addModifier(ele -> n.toSource()); } else { arg.addModifier(ele -> "todo->{}" ); } arg.addModifier(ele -> ");" ); super.visit(n, arg); } }