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.mapping;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.asm4.Type;
022    import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
023    import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
024    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
025    import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
026    import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
027    import org.jetbrains.jet.lang.resolve.name.FqName;
028    import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
029    import org.jetbrains.jet.lang.types.JetType;
030    import org.jetbrains.jet.lang.types.lang.PrimitiveType;
031    
032    import java.util.HashMap;
033    import java.util.Map;
034    
035    public class KotlinToJavaTypesMap extends JavaToKotlinClassMapBuilder {
036        private static KotlinToJavaTypesMap instance = null;
037    
038        @NotNull
039        public static KotlinToJavaTypesMap getInstance() {
040            if (instance == null) {
041                instance = new KotlinToJavaTypesMap();
042            }
043            return instance;
044        }
045    
046        private final Map<FqName, Type> asmTypes = new HashMap<FqName, Type>();
047        private final Map<FqName, Type> asmNullableTypes = new HashMap<FqName, Type>();
048    
049        private KotlinToJavaTypesMap() {
050            init();
051            initPrimitives();
052        }
053    
054        private void initPrimitives() {
055            for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
056                FqName className = jvmPrimitiveType.getPrimitiveType().getClassName();
057    
058                register(className, jvmPrimitiveType.getAsmType());
059                registerNullable(className, jvmPrimitiveType.getWrapper().getAsmType());
060            }
061            for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
062                PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
063                register(primitiveType.getArrayClassName(), jvmPrimitiveType.getAsmArrayType());
064            }
065        }
066    
067        @Nullable
068        public Type getJavaAnalog(@NotNull JetType jetType) {
069            ClassifierDescriptor classifier = jetType.getConstructor().getDeclarationDescriptor();
070            assert classifier != null;
071            FqNameUnsafe className = DescriptorUtils.getFQName(classifier);
072            if (!className.isSafe()) return null;
073            FqName fqName = className.toSafe();
074            if (jetType.isNullable()) {
075                Type nullableType = asmNullableTypes.get(fqName);
076                if (nullableType != null) {
077                    return nullableType;
078                }
079            }
080            return asmTypes.get(fqName);
081        }
082    
083        @Override
084        protected void register(@NotNull Class<?> javaClass, @NotNull ClassDescriptor kotlinDescriptor, @NotNull Direction direction) {
085            if (direction == Direction.BOTH || direction == Direction.KOTLIN_TO_JAVA) {
086                register(kotlinDescriptor, AsmTypeConstants.getType(javaClass));
087            }
088        }
089    
090        @Override
091        protected void register(
092                @NotNull Class<?> javaClass,
093                @NotNull ClassDescriptor kotlinDescriptor,
094                @NotNull ClassDescriptor kotlinMutableDescriptor,
095                @NotNull Direction direction
096        ) {
097            if (direction == Direction.BOTH || direction == Direction.KOTLIN_TO_JAVA) {
098                register(javaClass, kotlinDescriptor);
099                register(javaClass, kotlinMutableDescriptor);
100            }
101        }
102    
103        private void register(@NotNull ClassDescriptor kotlinDescriptor, @NotNull Type javaType) {
104            FqNameUnsafe fqName = DescriptorUtils.getFQName(kotlinDescriptor);
105            assert fqName.isSafe();
106            register(fqName.toSafe(), javaType);
107        }
108    
109        private void register(@NotNull FqName fqName, @NotNull Type type) {
110            asmTypes.put(fqName, type);
111        }
112    
113        private void registerNullable(@NotNull FqName fqName, @NotNull Type nullableType) {
114            asmNullableTypes.put(fqName, nullableType);
115        }
116    }