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.resolve.jvm;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.kotlin.name.ClassId;
021    import org.jetbrains.kotlin.name.FqName;
022    
023    public class JvmClassName {
024        @NotNull
025        public static JvmClassName byInternalName(@NotNull String internalName) {
026            return new JvmClassName(internalName);
027        }
028    
029        @NotNull
030        public static JvmClassName byClassId(@NotNull ClassId classId) {
031            FqName packageFqName = classId.getPackageFqName();
032            String relativeClassName = classId.getRelativeClassName().asString().replace('.', '$');
033            return packageFqName.isRoot()
034                   ? new JvmClassName(relativeClassName)
035                   : new JvmClassName(packageFqName.asString().replace('.', '/') + "/" + relativeClassName);
036        }
037    
038        /**
039         * WARNING: fq name cannot be uniquely mapped to JVM class name.
040         */
041        @NotNull
042        public static JvmClassName byFqNameWithoutInnerClasses(@NotNull FqName fqName) {
043            JvmClassName r = new JvmClassName(fqName.asString().replace('.', '/'));
044            r.fqName = fqName;
045            return r;
046        }
047    
048        @NotNull
049        public static JvmClassName byFqNameWithoutInnerClasses(@NotNull String fqName) {
050            return byFqNameWithoutInnerClasses(new FqName(fqName));
051        }
052    
053        // Internal name:  kotlin/Map$Entry
054        // FqName:         kotlin.Map.Entry
055    
056        private final String internalName;
057        private FqName fqName;
058    
059        private JvmClassName(@NotNull String internalName) {
060            this.internalName = internalName;
061        }
062    
063        /**
064         * WARNING: internal name cannot be converted to FQ name for a class which contains dollars in the name
065         */
066        @NotNull
067        public FqName getFqNameForClassNameWithoutDollars() {
068            if (fqName == null) {
069                this.fqName = new FqName(internalName.replace('$', '.').replace('/', '.'));
070            }
071            return fqName;
072        }
073    
074        @NotNull
075        public FqName getPackageFqName() {
076            int lastSlash = internalName.lastIndexOf("/");
077            if (lastSlash == -1) return FqName.ROOT;
078            return new FqName(internalName.substring(0, lastSlash).replace('/', '.'));
079        }
080    
081        @NotNull
082        public String getInternalName() {
083            return internalName;
084        }
085    
086        @Override
087        public String toString() {
088            return internalName;
089        }
090    
091        @Override
092        public boolean equals(Object o) {
093            if (this == o) return true;
094            if (o == null || getClass() != o.getClass()) return false;
095            return internalName.equals(((JvmClassName) o).internalName);
096        }
097    
098        @Override
099        public int hashCode() {
100            return internalName.hashCode();
101        }
102    }