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.search.GlobalSearchScope;
021    import kotlin.CollectionsKt;
022    import kotlin.jvm.functions.Function1;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.kotlin.load.java.structure.*;
025    import org.jetbrains.kotlin.name.Name;
026    
027    import java.util.ArrayList;
028    import java.util.Collection;
029    import java.util.Collections;
030    import java.util.List;
031    
032    public class JavaElementCollectionFromPsiArrayUtil {
033        private JavaElementCollectionFromPsiArrayUtil() {
034        }
035    
036        private interface Factory<Psi, Java> {
037            @NotNull
038            Java create(@NotNull Psi psi);
039        }
040    
041        private static class Factories {
042            private static final Factory<PsiClass, JavaClass> CLASSES = new Factory<PsiClass, JavaClass>() {
043                @NotNull
044                @Override
045                public JavaClass create(@NotNull PsiClass psiClass) {
046                    return new JavaClassImpl(psiClass);
047                }
048            };
049    
050            private static final Factory<PsiMethod, JavaMethod> METHODS = new Factory<PsiMethod, JavaMethod>() {
051                @NotNull
052                @Override
053                public JavaMethod create(@NotNull PsiMethod psiMethod) {
054                    return new JavaMethodImpl(psiMethod);
055                }
056            };
057    
058            private static final Factory<PsiMethod, JavaConstructor> CONSTRUCTORS = new Factory<PsiMethod, JavaConstructor>() {
059                @NotNull
060                @Override
061                public JavaConstructor create(@NotNull PsiMethod psiMethod) {
062                    return new JavaConstructorImpl(psiMethod);
063                }
064            };
065    
066            private static final Factory<PsiField, JavaField> FIELDS = new Factory<PsiField, JavaField>() {
067                @NotNull
068                @Override
069                public JavaField create(@NotNull PsiField psiField) {
070                    return new JavaFieldImpl(psiField);
071                }
072            };
073    
074            private static final Factory<PsiParameter, JavaValueParameter> VALUE_PARAMETERS = new Factory<PsiParameter, JavaValueParameter>() {
075                @NotNull
076                @Override
077                public JavaValueParameter create(@NotNull PsiParameter psiParameter) {
078                    return new JavaValueParameterImpl(psiParameter);
079                }
080            };
081    
082            private static final Factory<PsiTypeParameter, JavaTypeParameter> TYPE_PARAMETERS =
083                    new Factory<PsiTypeParameter, JavaTypeParameter>() {
084                @NotNull
085                @Override
086                public JavaTypeParameter create(@NotNull PsiTypeParameter psiTypeParameter) {
087                    return new JavaTypeParameterImpl(psiTypeParameter);
088                }
089            };
090    
091            private static final Factory<PsiType, JavaType> TYPES = new Factory<PsiType, JavaType>() {
092                @NotNull
093                @Override
094                public JavaType create(@NotNull PsiType psiType) {
095                    return JavaTypeImpl.create(psiType);
096                }
097            };
098    
099            private static final Factory<PsiClassType, JavaClassifierType> CLASSIFIER_TYPES = new Factory<PsiClassType, JavaClassifierType>() {
100                @NotNull
101                @Override
102                public JavaClassifierType create(@NotNull PsiClassType psiClassType) {
103                    return new JavaClassifierTypeImpl(psiClassType);
104                }
105            };
106    
107            private static final Factory<PsiAnnotation, JavaAnnotation> ANNOTATIONS = new Factory<PsiAnnotation, JavaAnnotation>() {
108                @NotNull
109                @Override
110                public JavaAnnotation create(@NotNull PsiAnnotation psiAnnotation) {
111                    return new JavaAnnotationImpl(psiAnnotation);
112                }
113            };
114    
115            private static final Factory<PsiNameValuePair, JavaAnnotationArgument> NAMED_ANNOTATION_ARGUMENTS =
116                    new Factory<PsiNameValuePair, JavaAnnotationArgument>() {
117                @NotNull
118                @Override
119                public JavaAnnotationArgument create(@NotNull PsiNameValuePair psiNameValuePair) {
120                    String name = psiNameValuePair.getName();
121                    PsiAnnotationMemberValue value = psiNameValuePair.getValue();
122                    assert value != null : "Annotation argument value cannot be null: " + name;
123                    return JavaAnnotationArgumentImpl.Factory.create(value, name == null ? null : Name.identifier(name));
124                }
125            };
126        }
127    
128        @NotNull
129        private static <Psi, Java> List<Java> convert(@NotNull Psi[] elements, @NotNull Factory<Psi, Java> factory) {
130            if (elements.length == 0) return Collections.emptyList();
131            List<Java> result = new ArrayList<Java>(elements.length);
132            for (Psi element : elements) {
133                result.add(factory.create(element));
134            }
135            return result;
136        }
137    
138        @NotNull
139        private static <Psi, Java> List<Java> convert(@NotNull Iterable<Psi> elements, @NotNull final Factory<Psi, Java> factory) {
140            if (!elements.iterator().hasNext()) return Collections.emptyList();
141            return CollectionsKt.map(elements, new Function1<Psi, Java>() {
142                @Override
143                public Java invoke(Psi psi) {
144                    return factory.create(psi);
145                }
146            });
147        }
148    
149        @NotNull
150        public static Collection<JavaClass> classes(@NotNull PsiClass[] classes) {
151            return convert(classes, Factories.CLASSES);
152        }
153    
154        @NotNull
155        public static Collection<JavaClass> classes(@NotNull Iterable<PsiClass> classes) {
156            return convert(classes, Factories.CLASSES);
157        }
158    
159        @NotNull
160        public static Collection<JavaPackage> packages(@NotNull PsiPackage[] packages, @NotNull final GlobalSearchScope scope) {
161            return convert(packages, new Factory<PsiPackage, JavaPackage>() {
162                @NotNull
163                @Override
164                public JavaPackage create(@NotNull PsiPackage aPackage) {
165                    return new JavaPackageImpl(aPackage, scope);
166                }
167            });
168        }
169    
170        @NotNull
171        public static Collection<JavaMethod> methods(@NotNull PsiMethod[] methods) {
172            return convert(methods, Factories.METHODS);
173        }
174    
175        @NotNull
176        public static Collection<JavaMethod> methods(@NotNull Iterable<PsiMethod> methods) {
177            return convert(methods, Factories.METHODS);
178        }
179    
180        @NotNull
181        public static Collection<JavaConstructor> constructors(@NotNull Iterable<PsiMethod> methods) {
182            return convert(methods, Factories.CONSTRUCTORS);
183        }
184    
185        @NotNull
186        public static Collection<JavaField> fields(@NotNull Iterable<PsiField> fields) {
187            return convert(fields, Factories.FIELDS);
188        }
189    
190        @NotNull
191        public static List<JavaValueParameter> valueParameters(@NotNull PsiParameter[] parameters) {
192            return convert(parameters, Factories.VALUE_PARAMETERS);
193        }
194    
195        @NotNull
196        public static List<JavaTypeParameter> typeParameters(@NotNull PsiTypeParameter[] typeParameters) {
197            return convert(typeParameters, Factories.TYPE_PARAMETERS);
198        }
199    
200        @NotNull
201        public static List<JavaType> types(@NotNull PsiType[] types) {
202            return convert(types, Factories.TYPES);
203        }
204    
205        @NotNull
206        public static Collection<JavaClassifierType> classifierTypes(@NotNull PsiClassType[] classTypes) {
207            return convert(classTypes, Factories.CLASSIFIER_TYPES);
208        }
209    
210        @NotNull
211        public static Collection<JavaAnnotation> annotations(@NotNull PsiAnnotation[] annotations) {
212            return convert(annotations, Factories.ANNOTATIONS);
213        }
214    
215        @NotNull
216        public static Collection<JavaAnnotationArgument> namedAnnotationArguments(@NotNull PsiNameValuePair[] nameValuePairs) {
217            return convert(nameValuePairs, Factories.NAMED_ANNOTATION_ARGUMENTS);
218        }
219    }