package edu.ucsd.arcum.interpreter.fragments;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.SimpleName;
import edu.ucsd.arcum.exceptions.ArcumError;
import edu.ucsd.arcum.interpreter.query.Entity;
import edu.ucsd.arcum.interpreter.query.EntityType;
import edu.ucsd.arcum.interpreter.query.IEntityLookup;
import edu.ucsd.arcum.interpreter.satisfier.BindingMap;
import edu.ucsd.arcum.util.StringUtil;
// URGENT (!!!) -- Handle matching for the signature case; but will need to think
// of a better place to handle the signature coercion
public class ResolvedEntity extends ProgramFragment
{
private @Union("Entity") final Object entity;
public ResolvedEntity(ASTNode astNode) {
this.entity = astNode;
}
public ResolvedEntity(ModifierElement modifierElement) {
this.entity = modifierElement;
}
public ResolvedEntity(SignatureEntity signatureEntity) {
this.entity = signatureEntity;
}
public ResolvedEntity(String string) {
this.entity = string;
}
// Does the program fragment represent the given modifier element?
public static boolean represents(ProgramFragment frag, ModifierElement mod1) {
if (frag instanceof ResolvedEntity) {
ResolvedEntity resolvedEntity = (ResolvedEntity)frag;
if (resolvedEntity.entity instanceof ModifierElement) {
ModifierElement mod2 = (ModifierElement)resolvedEntity.entity;
if (mod1.equals(mod2)) {
return true;
}
}
}
return false;
}
// Does the program fragment represent a modifier element that's an access specifier?
public static boolean representsAccessSpecifier(ProgramFragment frag) {
if (frag instanceof ResolvedEntity) {
ResolvedEntity resolvedEntity = (ResolvedEntity)frag;
if (resolvedEntity.entity instanceof ModifierElement) {
ModifierElement mod = (ModifierElement)resolvedEntity.entity;
if (mod.isAccessSpecifier()) {
return true;
}
}
}
return false;
}
@Override
protected void buildString(StringBuilder buff) {
buff.append(getIndenter());
buff.append("(ResolvedEntity ");
buff.append(Entity.getDisplayString(entity));
buff.append(")");
}
@Override
public BindingMap generateNode(IEntityLookup lookup, AST ast) {
if (entity instanceof ASTNode) {
String id = lookup.lookupEntitiesID(entity);
return bindNamedRoot(copy(ast, ASTNode.class, (ASTNode)entity), id, EntityType.PUNT);
}
else {
return bindRoot(entity);
}
}
public Object getValue() {
return entity;
}
@Override
protected BindingMap matchesASTNode(ASTNode node) {
// MONDAY: Should this be compareTo or compareToWithLocations? And if it
// should be compareToWithLocations then the unification search can be
// greatly reduced when the fragment matched contains an instance of
// ResolvedEntity
if (Entity.compareToWithLocations(entity, node) == 0) {
return bindRoot(node);
}
else {
return null;
}
}
@Override
protected BindingMap matchesModifierElement(ModifierElement modifier) {
if (Entity.compareTo(entity, modifier) == 0) {
return bindRoot(modifier);
}
else {
return null;
}
}
@Override
protected BindingMap matchesSignatureEntity(SignatureEntity signature) {
ArcumError.fatalError("Unsupported case");
return null;
}
@Override
final protected BindingMap matchesSimpleProperty(Object node) {
if (node instanceof String) {
String text;
if (entity instanceof SimpleName) {
SimpleName name = (SimpleName)entity;
text = name.getIdentifier();
}
else if (entity instanceof String) {
text = (String)entity;
}
else {
text = null;
ArcumError.fatalError("Cannot handle string case with: %s", StringUtil
.debugDisplay(entity));
}
if (text.equals(node)) {
return bindRoot(node);
}
}
return null;
}
public static ProgramFragment newInstance(Object entity) {
ProgramFragment result;
if (entity instanceof ASTNode) {
result = new ResolvedEntity((ASTNode)entity);
}
else if (entity instanceof ModifierElement) {
result = new ResolvedEntity((ModifierElement)entity);
}
else if (entity instanceof SignatureEntity) {
result = new ResolvedEntity((SignatureEntity)entity);
}
else if (entity instanceof String) {
result = new ResolvedEntity((String)entity);
}
else if (entity instanceof ITypeBinding) {
result = new ResolvedType((ITypeBinding)entity);
}
else if (entity instanceof SubtreeList) {
result = (SubtreeList)entity;
}
else {
ArcumError.fatalError("Unhandled case: %s", entity);
return null;
}
return result;
}
@Override
public boolean isResolved() {
return true;
}
@Override
public BindingMap matchResolvedEntity() {
BindingMap result = bindRoot(entity);
return result;
}
}