001    package org.mesopotamia.lang.java;
002    
003    import java.util.List;
004    
005    import org.mesopotamia.LanguageElement;
006    import org.mesopotamia.MesopotamiaException;
007    import org.mesopotamia.NodeData;
008    import org.mesopotamia.RepositoryLanguage;
009    import org.mesopotamia.Scan;
010    import org.mesopotamia.lang.java.ref.MethodInfo;
011    import org.mesopotamia.lang.java.ref.Reference;
012    import org.mesopotamia.lang.java.ref.Scope;
013    import org.mesopotamia.lang.java.ref.TypeInfo;
014    import org.mesopotamia.lang.java.ref.TypeSpecInfo;
015    import org.w3c.dom.Element;
016    
017    import biz.hammurapi.util.CollectionVisitable;
018    import biz.hammurapi.util.Visitor;
019    
020    /**
021     * Method call implements scope as a shortcut
022     * @author Pavel
023     *
024     */
025    public class MethodCall extends PostfixExpression implements Reference<MethodInfo> {
026    
027            private Identifier nameElement;
028    
029            public MethodCall(NodeData xData, Class<?> context, Scan scan, RepositoryLanguage language, Object environment) throws MesopotamiaException {
030                    super(xData, context, scan, language, environment);
031                    nameElement = (Identifier) getChild(0);
032                    Arguments = select(Expression.class, "ELIST/*");
033            }
034    
035            public void toDom(Element holder) {
036                    super.toDom(holder);
037    
038                    // Serialize attributes
039                    setElement(holder, "name", nameElement);
040                    setElement(holder, "Arguments", Arguments);
041                    setElement(holder, "Provider", getProvider());
042            }
043    
044            // Attributes
045            private List<Expression> Arguments;
046    
047            // Accessors
048            public String getName() {
049                    return nameElement.getText();
050            }
051    
052            public LanguageElement getProvider() {
053                    return (LanguageElement) (nameElement.providerHandle == null ? null : getScan().getLanguageElement(nameElement.providerHandle));
054            }
055    
056            public List<Expression> getArguments() {
057                    return Arguments;
058            }
059    
060            protected void acceptChildren(Visitor visitor) {
061                    nameElement.accept(visitor);
062                    new CollectionVisitable(Arguments, false).accept(visitor);
063                    object2visitor(getProvider(), visitor);
064            }
065    
066            public List<TypeArgument> getTypeArguments() {
067                    return nameElement.getTypeArguments();
068            }
069            
070            public MethodInfo getInfo() {
071                    return getInfo(findParent(Scope.class));
072            }
073                    
074            public MethodInfo getInfo(Scope es) {
075                    
076                    List<Expression> args = getArguments();
077                    String[] argTypes = new String[args.size()];
078                    int idx=0;
079                    for (Expression arg: args) {
080                            argTypes[idx++] = TypeSpecification.toString(arg.getTypeSpecInfo());
081                    }
082                    
083                    LanguageElement provider = getProvider();
084                    if (provider == null) {
085                            if (es!=null) {
086                                    MethodInfo ret = es.findMethod(getName(), argTypes);
087                                    if (ret!=null) {
088                                            return ret;
089                                    }
090                            }
091                    } else {
092                            TypeSpecInfo typeSpecInfo = null;
093                            if (provider instanceof Identifier) {
094                                    typeSpecInfo = ((Identifier) provider).getTypeSpecInfo(es);
095                            } else if (provider instanceof MethodCall) {
096                                    typeSpecInfo = ((MethodCall) provider).getTypeSpecInfo(es);
097                            } else if (provider instanceof Expression) {
098                                     typeSpecInfo = ((Expression) provider).getTypeSpecInfo();
099                            }
100                            
101                            if (typeSpecInfo!=null) {
102                                    TypeInfo ti = TypeSpecification.toTypeInfo(typeSpecInfo, es);
103                                    if (ti!=null) {                                 
104                                            MethodInfo ret = ti.findTypeMethod(getName(), argTypes);
105                                            if (ret!=null) {
106                                                    return ret;
107                                            }
108                                    }
109                            }
110                    }
111                    return null;
112            }
113            
114            @Override
115            public TypeSpecInfo getTypeSpecInfo() {
116                    return getTypeSpecInfo(findParent(Scope.class));
117            }
118    
119            public TypeSpecInfo getTypeSpecInfo(Scope es) {
120                    MethodInfo info = getInfo(es);
121                    return info==null ? null : info.getReturnType();
122            }
123    
124    }