package edu.ucsd.arcum.interpreter.fragments; import static edu.ucsd.arcum.ArcumPlugin.DEBUG; import java.util.*; import java.util.Map.Entry; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; import com.google.common.collect.Lists; import edu.ucsd.arcum.interpreter.query.IEntityLookup; import edu.ucsd.arcum.interpreter.satisfier.BindingMap; import edu.ucsd.arcum.interpreter.transformation.Conversion; public class PartialNode extends ProgramFragment { private Class rootType; private Map<StructuralPropertyDescriptor, ProgramFragment> children; private ArrayList<StructuralPropertyDescriptor> iterationOrder; public PartialNode(Class rootType) { this.rootType = rootType; this.children = new IdentityHashMap<StructuralPropertyDescriptor, ProgramFragment>( 5); this.iterationOrder = Lists.newArrayList(); } public void addBranch(StructuralPropertyDescriptor edge, ProgramFragment branch) { children.put(edge, branch); iterationOrder.add(edge); } // Removing a branch means that its value won't be taken into consideration // during matching public void removeBranch(StructuralPropertyDescriptor spd) { children.remove(spd); iterationOrder.remove(spd); } @Override protected void buildString(StringBuilder buff) { buff.append(getIndenter()); buff.append("("); buff.append(rootType.getSimpleName()); getIndenter().indent(); for (Map.Entry<StructuralPropertyDescriptor, ProgramFragment> child : children .entrySet()) { buff.append(getIndenter().newLine()); buff.append("<"); buff.append(child.getKey().getId()); buff.append(String.format(">%n")); ProgramFragment value = child.getValue(); if (value != null) { value.buildString(buff); } else { buff.append(getIndenter()); buff.append("<<null>>"); } } buff.append(")"); getIndenter().unindent(); } @Override public BindingMap generateNode(IEntityLookup lookup, AST ast) { ASTNode node = ast.createInstance(rootType); BindingMap result = bindRoot(node); for (StructuralPropertyDescriptor spd : iterationOrder) { ProgramFragment childPattern = children.get(spd); BindingMap child = childPattern.generateNode(lookup, ast); result = result.consistentMerge(child); Object entity = child.getResult(); if (spd.isChildListProperty()) { List structuralASTList = (List)node.getStructuralProperty(spd); EntityList entityList = (EntityList)entity; int numMembers = entityList.size(); for (int i = 0; i < numMembers; ++i) { Object listMember = entityList.getEntity(i); ProgramFragment fragment = entityList.getFragment(i); ASTNode n = Conversion.toPossibleEmptyNode(ast, spd, listMember); if (n != null) { structuralASTList.add(n); result.boundValueUpdated(listMember, n); } } } else if (spd.isChildProperty()) { Object originalValue = entity; entity = Conversion.toPossibleEmptyNode(ast, spd, entity); if (entity != null) { entity = Conversion.unbox(ast, spd, (ASTNode)entity); node.setStructuralProperty(spd, entity); result.boundValueUpdated(originalValue, entity); } } else { entity = Conversion.toSimpleProperty(entity); node.setStructuralProperty(spd, entity); } } return result; } public Class getRootType() { return rootType; } @Override protected BindingMap matchesASTNode(ASTNode node) { if (rootType.isInstance(node)) { Set<Entry<StructuralPropertyDescriptor, ProgramFragment>> entrySet; Iterator<Entry<StructuralPropertyDescriptor, ProgramFragment>> it; Entry<StructuralPropertyDescriptor, ProgramFragment> entry; BindingMap result = bindRoot(node); entrySet = children.entrySet(); it = entrySet.iterator(); while (it.hasNext()) { entry = it.next(); StructuralPropertyDescriptor spd = entry.getKey(); ProgramFragment childPattern = entry.getValue(); @Union("Entity") Object childEntity = node.getStructuralProperty(spd); if (spd.isChildListProperty()) { SubtreeList listOfPatterns = (SubtreeList)childPattern; List childList = (List)childEntity; EntityList entityList = new EntityList(spd); int numChildren = childList.size(); for (int i = 0; i < numChildren; ++i) { Object childListElement = childList.get(i); if (numChildren == listOfPatterns.size()) { entityList.addEntity(childListElement, listOfPatterns.get(i)); } else { entityList.addEntity(childListElement, null); } } childEntity = entityList; } if (childEntity == null) { childEntity = new EmptyEntityInfo(node, spd); } BindingMap theta = childPattern.matches(childEntity); if (theta == null) { return null; } result.addBindings(theta); } if (DEBUG) { System.out.printf("Returning a match:%n[%s]%nwith:%n[%s]%n", this, node); } return result; } else { return null; } } @Override protected BindingMap matchesSignatureEntity(SignatureEntity signature) { return matchesASTNode(signature.getSignatureNode()); } public ProgramFragment lookupEdge(StructuralPropertyDescriptor edge) { return children.get(edge); } }