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.MesopotamiaNode;
008    import org.mesopotamia.NodeData;
009    import org.mesopotamia.RepositoryLanguage;
010    import org.mesopotamia.Scan;
011    import org.mesopotamia.lang.java.ref.Info;
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.mesopotamia.lang.java.ref.VariableInfo;
016    import org.mesopotamia.util.UnmodifiableConvertingList;
017    import org.w3c.dom.Element;
018    
019    import biz.hammurapi.util.CollectionVisitable;
020    import biz.hammurapi.util.Visitor;
021    
022    public class Identifier extends PrimaryExpression implements Type {
023    
024            public Identifier(NodeData xData, Class<?> context, Scan scan,    RepositoryLanguage language, Object environment) throws MesopotamiaException {
025                    super(xData, context, scan, language, environment);
026            }
027            
028            public void toDom(Element holder) {
029                    super.toDom(holder);
030    
031                    // Serialize attributes
032                    setElement(holder, "TypeArguments", TypeArguments);
033            }
034    
035            // Attributes
036            private UnmodifiableConvertingList<TypeArgument> TypeArguments;
037    
038            /**
039             * Full text with dots.
040             */
041            public String getPath() {
042                    if (providerHandle==null) {
043                            return nodeText(getNode());
044                    }
045                    
046                    MesopotamiaNode providerNode = getSourceUnit().getSyntaxTree().findNode(providerHandle.getId());
047                    return nodeText("DOT".equals(providerNode.getParent().getTypeName()) ? providerNode.getParent() : providerNode); 
048            }
049    
050            // Accessors
051            public List<TypeArgument> getTypeArguments() {
052                    return TypeArguments;
053            }
054    
055            protected void acceptChildren(Visitor visitor) {
056                    // super.acceptChildren(visitor);
057                    // Visiting non-text attributes
058                    new CollectionVisitable(TypeArguments, false).accept(visitor);
059            }
060                    
061            /**
062             * Constructs string from DOT tree.
063             * @param mn
064             * @return
065             */
066            public static String nodeText(MesopotamiaNode mn) {
067                    if ("DOT".equals(mn.getTypeName()) && mn.getChildren().size()==2) {
068                            return nodeText((MesopotamiaNode) mn.getChildren().get(0))+"."+nodeText((MesopotamiaNode) mn.getChildren().get(1));
069                    }
070                    
071                    if ("IDENT".equals(mn.getTypeName())) {
072                            return mn.getText();
073                    }
074                    
075                    if (mn.getChildren().size()==1) {
076                            return nodeText((MesopotamiaNode) mn.getChildren().get(0));
077                    }
078                    
079                    return null;
080            }
081    
082            public Info getInfo() {
083                    return getInfo(findParent(Scope.class));
084            }
085            
086            Info getInfo(Scope es) {
087                    if (getText()==null) {
088                            return null;
089                    }
090                    LanguageElement provider = getProvider();
091                    if (provider == null) {
092                            if (es!=null) {
093                                    VariableInfo ret = es.findVariable(getText());
094                                    if (ret!=null) {
095                                            return ret;
096                                    }
097                                    return es.findType(getText());
098                            }
099                    } else {
100                            TypeSpecInfo typeSpecInfo = null;
101                            if (provider instanceof Identifier) {
102                                    typeSpecInfo = ((Identifier) provider).getTypeSpecInfo(es);
103                            } else if (provider instanceof MethodCall) {
104                                    typeSpecInfo = ((MethodCall) provider).getTypeSpecInfo(es);
105                            } else if (provider instanceof Expression) {
106                                     typeSpecInfo = ((Expression) provider).getTypeSpecInfo();
107                            }
108                            
109                            if (typeSpecInfo!=null) {
110                                    TypeInfo ti = TypeSpecification.toTypeInfo(typeSpecInfo, es);
111                                    if (ti!=null) {                                 
112                                            TypeInfo type = ti.findNestedType(getText());
113                                            if (type!=null) {
114                                                    return type;
115                                            }
116                                            return ti.findTypeVariable(getText());
117                                    }
118                            }
119                            
120                            // FCN?
121                            if (es!=null) {
122                                    String path = getPath();
123                                    VariableInfo vi = es.findVariable(path);
124                                    if (vi!=null) {
125                                            return vi;
126                                    } 
127                                    
128                                    TypeInfo ti = es.findType(path);
129                                    if (ti!=null) {
130                                            return ti;
131                                    }
132                                    
133                            }                               
134                    }
135                    return null;
136            }
137            
138            @Override
139            public TypeSpecInfo getTypeSpecInfo() {
140                    return getTypeSpecInfo(findParent(Scope.class));
141            }
142    
143            public TypeSpecInfo getTypeSpecInfo(Scope scope) {
144                    final Info info = getInfo(scope);
145                    if (info instanceof TypeInfo) {
146                            return new TypeSpecInfo() {
147    
148                                    public int getDimensions() {
149                                            return 0;
150                                    }
151    
152                                    public TypeInfo getTypeInfo() {
153                                            return (TypeInfo) info;
154                                    }
155                                    
156                            };
157                    } else if (info instanceof VariableInfo) {
158                            return ((VariableInfo) info).getTypeSpecification();
159                    }
160                    return null;
161            }
162            
163    }