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.Scope;
012    import org.mesopotamia.lang.java.ref.TypeInfo;
013    import org.mesopotamia.lang.java.ref.TypeSpecInfo;
014    import org.mesopotamia.lang.java.ref.VariableInfo;
015    import org.w3c.dom.Element;
016    
017    import biz.hammurapi.util.Visitable;
018    import biz.hammurapi.util.Visitor;
019    
020    public class TypeSpecification extends TypeArgument implements TypeSpecInfo {
021    
022            private int dimensions;
023            private Type type;
024    
025            public TypeSpecification(
026                            NodeData xData, 
027                            Class<?> context, 
028                            Scan scan,
029                            RepositoryLanguage language, 
030                            Object environment) throws MesopotamiaException {
031                    super(xData, context, scan, language, environment);
032                    LanguageElement child=getChild(0);
033                    while ("ARRAY_DECLARATOR".equals(child.getTokenName())) {
034                            dimensions++;
035                            child=child.getChild(0);
036                    }
037                    
038                    type=(Type) child;
039            }
040            
041            /**
042             * Array dimensons.
043             * @return
044             */
045            public int getDimensions() {
046                    return dimensions;
047            }
048            
049            public Type getSpecificationType() {
050                    return type;
051            }
052    
053            public void toDom(Element holder) {
054                    super.toDom(holder);
055                    setAttribute(holder, "dimensions", String.valueOf(dimensions));
056                    setElement(holder, "type", type);
057            }
058            
059            protected void acceptChildren(Visitor visitor) {
060                    super.acceptChildren(visitor);
061                    ((Visitable) type).accept(visitor);
062            }
063            
064            public TypeInfo getTypeInfo() {
065                    if (type instanceof BuiltInType) {
066                            return (TypeInfo) type.getInfo();
067                    }
068                    // Can be only identifier here.
069                    String typeName = ((Identifier) type).getPath();
070                    Scope ec = findParent(Scope.class);
071                    return ec==null ? null : ec.findType(typeName);
072            }
073    
074            public static String toString(TypeSpecInfo typeSpecInfo) {
075                    if (typeSpecInfo == null) {
076                            return null;
077                    }
078                    TypeInfo ti = typeSpecInfo.getTypeInfo();
079                    if (ti==null) {
080                            return null;
081                    }                               
082                    String tfcn = ti.getFcn();
083                    StringBuffer ret = new StringBuffer(tfcn);
084                    for (int i=0; typeSpecInfo!=Null.NULL_TYPE_SPEC_INFO && i<typeSpecInfo.getDimensions(); ++i) {
085                            ret.append(ARRAY_BRACKETS);
086                    }
087                    return ret.toString();
088            }
089            
090            /**
091             * Returns type info for given type spec info taking dimensions
092             * into consideration.
093             * @param tsi
094             * @param es
095             * @return
096             */
097            public static TypeInfo toTypeInfo(TypeSpecInfo tsi, Scope es) {
098                    if (tsi==null) {
099                            return null;
100                    }
101                    
102                    if (tsi.getDimensions()==0) {
103                            return tsi.getTypeInfo();
104                    }
105                    
106                    if (es==null) {
107                            return null;
108                    }
109                    
110                    final TypeInfo objType = es.findType(JAVA_LANG_OBJECT);
111                    if (objType==null) {
112                            return null;
113                    }
114                    
115                    return new TypeInfo() {
116    
117                            public TypeInfo findNestedType(String name) {
118                                    return objType.findNestedType(name);
119                            }
120    
121                            public MethodInfo findTypeMethod(String name, String[] parameterTypes) {
122                                    return objType.findTypeMethod(name, parameterTypes);
123                            }
124    
125                            public VariableInfo findTypeVariable(String name) {
126                                    if ("length".equals(name)) {
127                                            return new VariableInfo() {
128    
129                                                    public TypeSpecInfo getTypeSpecification() {
130                                                            return new TypeSpecInfo() {
131    
132                                                                    public int getDimensions() {
133                                                                            return 0;
134                                                                    }
135    
136                                                                    public TypeInfo getTypeInfo() {
137                                                                            return Int.INT_INFO;                                                                                            }
138                                                                    
139                                                            };
140                                                    }
141    
142                                                    public TypeInfo getDeclaringType() {
143                                                            return null;
144                                                    }
145    
146                                                    public String getFcn() {
147                                                            return null;
148                                                    }
149    
150                                                    public List<String> getModifiers() {
151                                                            return null;
152                                                    }
153    
154                                                    public String getName() {
155                                                            return "length";
156                                                    }
157                                                    
158                                            };
159                                    }
160                                    return objType.findTypeVariable(name);
161                            }
162    
163                            public boolean isKindOf(String superFcn) {
164                                    return objType.isKindOf(superFcn);
165                            }
166    
167                            public TypeInfo getDeclaringType() {
168                                    return null;
169                            }
170    
171                            public String getFcn() {
172                                    return null;
173                            }
174    
175                            public List<String> getModifiers() {
176                                    return null;
177                            }
178    
179                            public String getName() {
180                                    return null;
181                            }
182    
183                            public MethodInfo findConstructor(String[] parameterTypes) {
184                                    return null;
185                            }
186                            
187                    };
188            }
189            
190    }