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.name;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.kotlin.utils.StringsKt;
021    
022    import java.util.List;
023    
024    public final class FqName {
025    
026        @NotNull
027        public static FqName fromSegments(@NotNull List<String> names) {
028            return new FqName(StringsKt.join(names, "."));
029        }
030    
031        public static final FqName ROOT = new FqName("");
032    
033        @NotNull
034        private final FqNameUnsafe fqName;
035    
036        // cache
037        private transient FqName parent;
038    
039        public FqName(@NotNull String fqName) {
040            this.fqName = new FqNameUnsafe(fqName, this);
041        }
042    
043        public FqName(@NotNull FqNameUnsafe fqName) {
044            this.fqName = fqName;
045        }
046    
047        private FqName(@NotNull FqNameUnsafe fqName, FqName parent) {
048            this.fqName = fqName;
049            this.parent = parent;
050        }
051    
052        @NotNull
053        public String asString() {
054            return fqName.asString();
055        }
056    
057        @NotNull
058        public FqNameUnsafe toUnsafe() {
059            return fqName;
060        }
061    
062        public boolean isRoot() {
063            return fqName.isRoot();
064        }
065    
066        @NotNull
067        public FqName parent() {
068            if (parent != null) {
069                return parent;
070            }
071    
072            if (isRoot()) {
073                throw new IllegalStateException("root");
074            }
075    
076            parent = new FqName(fqName.parent());
077    
078            return parent;
079        }
080    
081        @NotNull
082        public FqName child(@NotNull Name name) {
083            return new FqName(fqName.child(name), this);
084        }
085    
086        @NotNull
087        public Name shortName() {
088            return fqName.shortName();
089        }
090    
091        @NotNull
092        public Name shortNameOrSpecial() {
093            return fqName.shortNameOrSpecial();
094        }
095    
096        @NotNull
097        public List<Name> pathSegments() {
098            return fqName.pathSegments();
099        }
100    
101        @NotNull
102        public static FqName topLevel(@NotNull Name shortName) {
103            return new FqName(FqNameUnsafe.topLevel(shortName));
104        }
105    
106        @Override
107        public String toString() {
108            return fqName.toString();
109        }
110    
111        @Override
112        public boolean equals(Object o) {
113            if (this == o) return true;
114            if (!(o instanceof FqName)) return false;
115    
116            FqName otherFqName = (FqName) o;
117    
118            if (!fqName.equals(otherFqName.fqName)) return false;
119    
120            return true;
121        }
122    
123        @Override
124        public int hashCode() {
125            return fqName.hashCode();
126        }
127    }