001    /*
002     * Copyright 2010-2015 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.kotlin.load.java.structure.impl;
018    
019    import com.intellij.psi.*;
020    import com.intellij.psi.impl.PsiSubstitutorImpl;
021    import kotlin.KotlinPackage;
022    import kotlin.jvm.functions.Function1;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.kotlin.asJava.JetJavaMirrorMarker;
026    import org.jetbrains.kotlin.descriptors.Visibility;
027    import org.jetbrains.kotlin.load.java.structure.*;
028    import org.jetbrains.kotlin.name.FqName;
029    import org.jetbrains.kotlin.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.kotlin.load.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            // ex. Android plugin generates LightFields for resources started from '.' (.DS_Store file etc)
113            return fields(KotlinPackage.filter(getPsi().getFields(), new Function1<PsiField, Boolean>() {
114                @Override
115                public Boolean invoke(PsiField field) {
116                    String name = field.getName();
117                    return name != null && Name.isValidIdentifier(name);
118                }
119            }));
120        }
121    
122        @Override
123        @NotNull
124        public Collection<JavaConstructor> getConstructors() {
125            return constructors(KotlinPackage.filter(getPsi().getConstructors(), new Function1<PsiMethod, Boolean>() {
126                @Override
127                public Boolean invoke(PsiMethod method) {
128                    // See for example org.jetbrains.plugins.scala.lang.psi.light.ScFunctionWrapper,
129                    // which is present in getConstructors(), but its isConstructor() returns false
130                    return method.isConstructor();
131                }
132            }));
133        }
134    
135        @Override
136        public boolean isAbstract() {
137            return JavaElementUtil.isAbstract(this);
138        }
139    
140        @Override
141        public boolean isStatic() {
142            return JavaElementUtil.isStatic(this);
143        }
144    
145        @Override
146        public boolean isFinal() {
147            return JavaElementUtil.isFinal(this);
148        }
149    
150        @NotNull
151        @Override
152        public Visibility getVisibility() {
153            return JavaElementUtil.getVisibility(this);
154        }
155    
156        @Override
157        @NotNull
158        public JavaClassifierType getDefaultType() {
159            return new JavaClassifierTypeImpl(JavaPsiFacade.getElementFactory(getPsi().getProject()).createType(getPsi()));
160        }
161    
162        @Override
163        @NotNull
164        public OriginKind getOriginKind() {
165            PsiClass psiClass = getPsi();
166            if (psiClass instanceof JetJavaMirrorMarker) {
167                return OriginKind.KOTLIN_LIGHT_CLASS;
168            }
169            else if (psiClass instanceof PsiCompiledElement) {
170                return OriginKind.COMPILED;
171            }
172            else {
173                return OriginKind.SOURCE;
174            }
175        }
176    
177        @NotNull
178        @Override
179        public JavaType createImmediateType(@NotNull JavaTypeSubstitutor substitutor) {
180            return new JavaClassifierTypeImpl(
181                    JavaPsiFacade.getElementFactory(getPsi().getProject()).createType(getPsi(), createPsiSubstitutor(substitutor)));
182        }
183    
184        @NotNull
185        private static PsiSubstitutor createPsiSubstitutor(@NotNull JavaTypeSubstitutor substitutor) {
186            Map<PsiTypeParameter, PsiType> substMap = new HashMap<PsiTypeParameter, PsiType>();
187            for (Map.Entry<JavaTypeParameter, JavaType> entry : substitutor.getSubstitutionMap().entrySet()) {
188                PsiTypeParameter key = ((JavaTypeParameterImpl) entry.getKey()).getPsi();
189                if (entry.getValue() == null) {
190                    substMap.put(key, null);
191                }
192                else {
193                    substMap.put(key, ((JavaTypeImpl) entry.getValue()).getPsi());
194                }
195            }
196    
197            return PsiSubstitutorImpl.createSubstitutor(substMap);
198        }
199    }