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 kotlin.Function1;
022    import kotlin.KotlinPackage;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.jet.lang.descriptors.Visibility;
026    import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetJavaMirrorMarker;
027    import org.jetbrains.jet.lang.resolve.java.structure.*;
028    import org.jetbrains.jet.lang.resolve.name.FqName;
029    import org.jetbrains.jet.lang.resolve.name.Name;
030    
031    import java.util.Collection;
032    import java.util.HashMap;
033    import java.util.List;
034    import java.util.Map;
035    
036    import static org.jetbrains.jet.lang.resolve.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.*;
037    
038    public class JavaClassImpl extends JavaClassifierImpl<PsiClass> implements JavaClass, JavaAnnotationOwnerImpl, JavaModifierListOwnerImpl {
039        public JavaClassImpl(@NotNull PsiClass psiClass) {
040            super(psiClass);
041            assert !(psiClass instanceof PsiTypeParameter)
042                    : "PsiTypeParameter should be wrapped in JavaTypeParameter, not JavaClass: use JavaClassifier.create()";
043        }
044    
045        @Override
046        @NotNull
047        public Collection<JavaClass> getInnerClasses() {
048            return classes(getPsi().getInnerClasses());
049        }
050    
051        @Override
052        @Nullable
053        public FqName getFqName() {
054            String qualifiedName = getPsi().getQualifiedName();
055            return qualifiedName == null ? null : new FqName(qualifiedName);
056        }
057    
058        @NotNull
059        @Override
060        public Name getName() {
061            return Name.identifier(getPsi().getName());
062        }
063    
064        @Override
065        public boolean isInterface() {
066            return getPsi().isInterface();
067        }
068    
069        @Override
070        public boolean isAnnotationType() {
071            return getPsi().isAnnotationType();
072        }
073    
074        @Override
075        public boolean isEnum() {
076            return getPsi().isEnum();
077        }
078    
079        @Override
080        @Nullable
081        public JavaClass getOuterClass() {
082            PsiClass outer = getPsi().getContainingClass();
083            return outer == null ? null : new JavaClassImpl(outer);
084        }
085    
086        @NotNull
087        @Override
088        public List<JavaTypeParameter> getTypeParameters() {
089            return typeParameters(getPsi().getTypeParameters());
090        }
091    
092        @Override
093        @NotNull
094        public Collection<JavaClassifierType> getSupertypes() {
095            return classifierTypes(getPsi().getSuperTypes());
096        }
097    
098        @Override
099        @NotNull
100        public Collection<JavaMethod> getMethods() {
101            return methods(KotlinPackage.filter(getPsi().getMethods(), new Function1<PsiMethod, Boolean>() {
102                @Override
103                public Boolean invoke(PsiMethod method) {
104                    return !method.isConstructor();
105                }
106            }));
107        }
108    
109        @Override
110        @NotNull
111        public Collection<JavaField> getFields() {
112            return fields(getPsi().getFields());
113        }
114    
115        @Override
116        @NotNull
117        public Collection<JavaConstructor> getConstructors() {
118            return constructors(getPsi().getConstructors());
119        }
120    
121        @Override
122        public boolean isAbstract() {
123            return JavaElementUtil.isAbstract(this);
124        }
125    
126        @Override
127        public boolean isStatic() {
128            return JavaElementUtil.isStatic(this);
129        }
130    
131        @Override
132        public boolean isFinal() {
133            return JavaElementUtil.isFinal(this);
134        }
135    
136        @NotNull
137        @Override
138        public Visibility getVisibility() {
139            return JavaElementUtil.getVisibility(this);
140        }
141    
142        @NotNull
143        @Override
144        public Collection<JavaAnnotation> getAnnotations() {
145            return JavaElementUtil.getAnnotations(this);
146        }
147    
148        @Nullable
149        @Override
150        public JavaAnnotation findAnnotation(@NotNull FqName fqName) {
151            return JavaElementUtil.findAnnotation(this, fqName);
152        }
153    
154        @Override
155        @NotNull
156        public JavaClassifierType getDefaultType() {
157            return new JavaClassifierTypeImpl(JavaPsiFacade.getElementFactory(getPsi().getProject()).createType(getPsi()));
158        }
159    
160        @Override
161        @NotNull
162        public OriginKind getOriginKind() {
163            PsiClass psiClass = getPsi();
164            if (psiClass instanceof JetJavaMirrorMarker) {
165                return OriginKind.KOTLIN_LIGHT_CLASS;
166            }
167            else if (psiClass instanceof PsiCompiledElement) {
168                return OriginKind.COMPILED;
169            }
170            else {
171                return OriginKind.SOURCE;
172            }
173        }
174    
175        @NotNull
176        @Override
177        public JavaType createImmediateType(@NotNull JavaTypeSubstitutor substitutor) {
178            return new JavaClassifierTypeImpl(
179                    JavaPsiFacade.getElementFactory(getPsi().getProject()).createType(getPsi(), createPsiSubstitutor(substitutor)));
180        }
181    
182        @NotNull
183        private static PsiSubstitutor createPsiSubstitutor(@NotNull JavaTypeSubstitutor substitutor) {
184            Map<PsiTypeParameter, PsiType> substMap = new HashMap<PsiTypeParameter, PsiType>();
185            for (Map.Entry<JavaTypeParameter, JavaType> entry : substitutor.getSubstitutionMap().entrySet()) {
186                PsiTypeParameter key = ((JavaTypeParameterImpl) entry.getKey()).getPsi();
187                if (entry.getValue() == null) {
188                    substMap.put(key, null);
189                }
190                else {
191                    substMap.put(key, ((JavaTypeImpl) entry.getValue()).getPsi());
192                }
193            }
194    
195            return PsiSubstitutorImpl.createSubstitutor(substMap);
196        }
197    }