package org.reuseware.air.language.abstractsyntax.resource.as.analysis;
import java.util.Map;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.InternalEObject;
import org.reuseware.air.language.abstractsyntax.AbstractSyntax;
import org.reuseware.air.language.abstractsyntax.ConcreteNodeDefinition;
import org.reuseware.air.language.abstractsyntax.Definition;
import org.reuseware.air.language.abstractsyntax.InterfaceNodeDefinition;
import org.reuseware.air.language.abstractsyntax.InternalReference;
import org.reuseware.air.language.abstractsyntax.NodeFeature;
import org.reuseware.air.language.abstractsyntax.resource.as.IAsContextDependentURIFragment;
import org.reuseware.air.language.abstractsyntax.resource.as.IAsReferenceResolveResult;
import org.reuseware.air.language.abstractsyntax.resource.as.IAsReferenceResolver;
import org.reuseware.air.language.abstractsyntax.resource.as.analysis.helper.DefinitionNamespaceResolverBase;
public class InternalReferenceOppositeReferenceResolver extends DefinitionNamespaceResolverBase<InternalReference,InternalReference> implements IAsReferenceResolver<InternalReference,InternalReference> {
public void resolve(String identifier, InternalReference container, EReference reference, int position, boolean resolveFuzzy, IAsReferenceResolveResult<InternalReference> result) {
InternalReference referenceDefinition = (InternalReference)container;
ConcreteNodeDefinition thisDefinition = (ConcreteNodeDefinition)referenceDefinition.eContainer();
Definition oppositeDefinition = referenceDefinition.getType();
ConcreteNodeDefinition targetDefinition = null;
if(oppositeDefinition instanceof InterfaceNodeDefinition){
targetDefinition = this.lookupConcreteDefinitions(oppositeDefinition.getName(),((AbstractSyntax)container.eResource().getContents().get(0)));
}
else if(oppositeDefinition instanceof ConcreteNodeDefinition){
targetDefinition = (ConcreteNodeDefinition)oppositeDefinition;
}
if(targetDefinition==null){
result.setErrorMessage("There's no concrete node definition with name '"+oppositeDefinition.getName()+"'.");
return;
}
for(NodeFeature feature:targetDefinition.getMembers()){
if((feature instanceof InternalReference)&&feature.getName().equals(identifier)){
InternalReference targetReference = (InternalReference)feature;
if(targetReference.getType().getName().equals(thisDefinition.getName())){
//1. case: targetReference has no defined opposite -> add mapping and set opposite
if(targetReference.getOpposite()==null){
result.addMapping(identifier,targetReference);
targetReference.setOpposite(referenceDefinition);
return;
}
else{
InternalEObject ieo = (InternalEObject)targetReference.getOpposite();
//2. case: targetReference has opposite, but opposite is proxy
if(ieo.eIsProxy()&&ieo.eProxyURI().fragment().startsWith(IAsContextDependentURIFragment.INTERNAL_URI_FRAGMENT_PREFIX)){
String proxyName = ieo.eProxyURI().fragment().substring(ieo.eProxyURI().fragment().lastIndexOf('_')+1);
if(proxyName.equals(referenceDefinition.getName())){
result.addMapping(identifier,targetReference);
return;
}
}
else if(targetReference.getOpposite().equals(referenceDefinition)){
result.addMapping(identifier,targetReference);
return;
}
}
}
}
}
result.setErrorMessage("Opposite resolving failed. Check if types of references match each other.");
}
public void setOptions(Map<?, ?> options) {
// TODO Auto-generated method stub
}
public String deResolve(InternalReference element,InternalReference container, EReference reference) {
return null;
}
}