001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.lang.resolve.java.structure.impl;
018    
019    import com.intellij.psi.*;
020    import com.intellij.psi.impl.PsiSubstitutorImpl;
021    import com.intellij.util.containers.ContainerUtil;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.jet.lang.descriptors.Visibility;
025    import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetJavaMirrorMarker;
026    import org.jetbrains.jet.lang.resolve.java.structure.*;
027    import org.jetbrains.jet.lang.resolve.name.FqName;
028    import org.jetbrains.jet.lang.resolve.name.Name;
029    
030    import java.util.Collection;
031    import java.util.HashMap;
032    import java.util.List;
033    import java.util.Map;
034    
035    import static org.jetbrains.jet.lang.resolve.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.*;
036    
037    public class JavaClassImpl extends JavaClassifierImpl<PsiClass> implements JavaClass, JavaAnnotationOwnerImpl, JavaModifierListOwnerImpl {
038        public JavaClassImpl(@NotNull PsiClass psiClass) {
039            super(psiClass);
040            assert !(psiClass instanceof PsiTypeParameter)
041                    : "PsiTypeParameter should be wrapped in JavaTypeParameter, not JavaClass: use JavaClassifier.create()";
042        }
043    
044        @Override
045        @NotNull
046        public Collection<JavaClass> getInnerClasses() {
047            return classes(getPsi().getInnerClasses());
048        }
049    
050        @Override
051        @Nullable
052        public FqName getFqName() {
053            String qualifiedName = getPsi().getQualifiedName();
054            return qualifiedName == null ? null : new FqName(qualifiedName);
055        }
056    
057        @NotNull
058        @Override
059        public Name getName() {
060            return Name.identifier(getPsi().getName());
061        }
062    
063        @Override
064        public boolean isInterface() {
065            return getPsi().isInterface();
066        }
067    
068        @Override
069        public boolean isAnnotationType() {
070            return getPsi().isAnnotationType();
071        }
072    
073        @Override
074        public boolean isEnum() {
075            return getPsi().isEnum();
076        }
077    
078        @Override
079        @Nullable
080        public JavaClass getOuterClass() {
081            PsiClass outer = getPsi().getContainingClass();
082            return outer == null ? null : new JavaClassImpl(outer);
083        }
084    
085        @NotNull
086        @Override
087        public List<JavaTypeParameter> getTypeParameters() {
088            return typeParameters(getPsi().getTypeParameters());
089        }
090    
091        @SuppressWarnings("unchecked")
092        @Override
093        @NotNull
094        public Collection<JavaClassifierType> getSupertypes() {
095            // TODO: getPsi().getSuperTypes() ?
096            Collection<JavaClassifierType> superClasses = classifierTypes(getPsi().getExtendsListTypes());
097            Collection<JavaClassifierType> superInterfaces = classifierTypes(getPsi().getImplementsListTypes());
098            return ContainerUtil.collect(ContainerUtil.concat(superClasses, superInterfaces).iterator());
099        }
100    
101        @Override
102        @NotNull
103        public Collection<JavaMethod> getMethods() {
104            return methods(getPsi().getMethods());
105        }
106    
107        @Override
108        @NotNull
109        public Collection<JavaMethod> getAllMethods() {
110            return methods(getPsi().getAllMethods());
111        }
112    
113        @Override
114        @NotNull
115        public Collection<JavaField> getFields() {
116            return fields(getPsi().getFields());
117        }
118    
119        @Override
120        @NotNull
121        public Collection<JavaField> getAllFields() {
122            return fields(getPsi().getAllFields());
123        }
124    
125        @Override
126        @NotNull
127        public Collection<JavaMethod> getConstructors() {
128            return methods(getPsi().getConstructors());
129        }
130    
131        @Override
132        public boolean isAbstract() {
133            return JavaElementUtil.isAbstract(this);
134        }
135    
136        @Override
137        public boolean isStatic() {
138            return JavaElementUtil.isStatic(this);
139        }
140    
141        @Override
142        public boolean isFinal() {
143            return JavaElementUtil.isFinal(this);
144        }
145    
146        @NotNull
147        @Override
148        public Visibility getVisibility() {
149            return JavaElementUtil.getVisibility(this);
150        }
151    
152        @NotNull
153        @Override
154        public Collection<JavaAnnotation> getAnnotations() {
155            return JavaElementUtil.getAnnotations(this);
156        }
157    
158        @Nullable
159        @Override
160        public JavaAnnotation findAnnotation(@NotNull FqName fqName) {
161            return JavaElementUtil.findAnnotation(this, fqName);
162        }
163    
164        @Override
165        @NotNull
166        public JavaClassifierType getDefaultType() {
167            return new JavaClassifierTypeImpl(JavaPsiFacade.getElementFactory(getPsi().getProject()).createType(getPsi()));
168        }
169    
170        @Override
171        @NotNull
172        public OriginKind getOriginKind() {
173            PsiClass psiClass = getPsi();
174            if (psiClass instanceof JetJavaMirrorMarker) {
175                return OriginKind.KOTLIN_LIGHT_CLASS;
176            }
177            else if (psiClass instanceof PsiCompiledElement) {
178                return OriginKind.COMPILED;
179            }
180            else {
181                return OriginKind.SOURCE;
182            }
183        }
184    
185        @NotNull
186        @Override
187        public JavaType createImmediateType(@NotNull JavaTypeSubstitutor substitutor) {
188            return new JavaClassifierTypeImpl(
189                    JavaPsiFacade.getElementFactory(getPsi().getProject()).createType(getPsi(), createPsiSubstitutor(substitutor)));
190        }
191    
192        @NotNull
193        private static PsiSubstitutor createPsiSubstitutor(@NotNull JavaTypeSubstitutor substitutor) {
194            Map<PsiTypeParameter, PsiType> substMap = new HashMap<PsiTypeParameter, PsiType>();
195            for (Map.Entry<JavaTypeParameter, JavaType> entry : substitutor.getSubstitutionMap().entrySet()) {
196                PsiTypeParameter key = ((JavaTypeParameterImpl) entry.getKey()).getPsi();
197                if (entry.getValue() == null) {
198                    substMap.put(key, null);
199                }
200                else {
201                    substMap.put(key, ((JavaTypeImpl) entry.getValue()).getPsi());
202                }
203            }
204    
205            return PsiSubstitutorImpl.createSubstitutor(substMap);
206        }
207    }