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.name;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.openapi.util.text.StringUtil;
021 import org.jetbrains.annotations.NotNull;
022
023 import java.util.List;
024
025 public class FqName extends FqNameBase {
026
027 @NotNull
028 public static FqName fromSegments(@NotNull List<String> names) {
029 String fqName = StringUtil.join(names, ".");
030 return new FqName(fqName);
031 }
032
033 public static final FqName ROOT = new FqName("");
034
035 @NotNull
036 private final FqNameUnsafe fqName;
037
038 // cache
039 private transient FqName parent;
040
041 public FqName(@NotNull String fqName) {
042 this.fqName = new FqNameUnsafe(fqName, this);
043
044 validateFqName();
045 }
046
047 public FqName(@NotNull FqNameUnsafe fqName) {
048 this.fqName = fqName;
049
050 validateFqName();
051 }
052
053 private FqName(@NotNull FqNameUnsafe fqName, FqName parent) {
054 this.fqName = fqName;
055 this.parent = parent;
056
057 validateFqName();
058 }
059
060
061 private void validateFqName() {
062 if (!isValidAfterUnsafeCheck(fqName.asString())) {
063 throw new IllegalArgumentException("incorrect fq name: " + fqName);
064 }
065 }
066
067 /*package*/ static boolean isValidAfterUnsafeCheck(@NotNull String qualifiedName) {
068 // TODO: There's a valid name with escape char ``
069 return qualifiedName.indexOf('<') < 0;
070 }
071
072 @Override
073 @NotNull
074 public String asString() {
075 return fqName.asString();
076 }
077
078 @NotNull
079 public FqNameUnsafe toUnsafe() {
080 return fqName;
081 }
082
083 public boolean isRoot() {
084 return fqName.isRoot();
085 }
086
087 @NotNull
088 public FqName parent() {
089 if (parent != null) {
090 return parent;
091 }
092
093 if (isRoot()) {
094 throw new IllegalStateException("root");
095 }
096
097 parent = new FqName(fqName.parent());
098
099 return parent;
100 }
101
102 @NotNull
103 public FqName child(@NotNull Name name) {
104 return new FqName(fqName.child(name), this);
105 }
106
107 @NotNull
108 public Name shortName() {
109 return fqName.shortName();
110 }
111
112 @NotNull
113 public Name shortNameOrSpecial() {
114 return fqName.shortNameOrSpecial();
115 }
116
117 @NotNull
118 public List<FqName> path() {
119 final List<FqName> path = Lists.newArrayList();
120 path.add(ROOT);
121 fqName.walk(new FqNameUnsafe.WalkCallback() {
122 @Override
123 public void segment(@NotNull Name shortName, @NotNull FqNameUnsafe fqName) {
124 // TODO: do not validate
125 path.add(new FqName(fqName));
126 }
127 });
128 return path;
129 }
130
131 @NotNull
132 public List<Name> pathSegments() {
133 return fqName.pathSegments();
134 }
135
136 public boolean firstSegmentIs(@NotNull Name segment) {
137 return fqName.firstSegmentIs(segment);
138 }
139
140 public boolean lastSegmentIs(@NotNull Name segment) {
141 return fqName.lastSegmentIs(segment);
142 }
143
144
145 @NotNull
146 public static FqName topLevel(@NotNull Name shortName) {
147 return new FqName(FqNameUnsafe.topLevel(shortName));
148 }
149
150
151 @Override
152 public String toString() {
153 return fqName.toString();
154 }
155
156 @Override
157 public boolean equals(Object o) {
158 // generated by Idea
159 if (this == o) return true;
160 if (o == null || getClass() != o.getClass()) return false;
161
162 FqName that = (FqName) o;
163
164 if (fqName != null ? !fqName.equals(that.fqName) : that.fqName != null) return false;
165
166 return true;
167 }
168
169 @Override
170 public int hashCode() {
171 // generated by Idea
172 return fqName != null ? fqName.hashCode() : 0;
173 }
174 }