001 package org.jetbrains.jet.descriptors.serialization;
002
003 import org.jetbrains.annotations.NotNull;
004 import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
005 import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
006 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
007 import org.jetbrains.jet.lang.resolve.name.FqName;
008 import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
009 import org.jetbrains.jet.lang.resolve.name.Name;
010
011 import java.util.List;
012
013 public final class ClassId {
014 private final FqName packageFqName;
015 private final FqNameUnsafe relativeClassName;
016
017 @NotNull
018 public static ClassId fromFqNameAndContainingDeclaration(
019 @NotNull FqNameUnsafe fqName,
020 @NotNull ClassOrNamespaceDescriptor containingDeclaration
021 ) {
022 NamespaceDescriptor containingNamespace = DescriptorUtils.getParentOfType(containingDeclaration, NamespaceDescriptor.class, false);
023 assert containingNamespace != null;
024 List<Name> fullNameSegments = fqName.pathSegments();
025 FqName namespaceFqName = DescriptorUtils.getFQName(containingNamespace).toSafe();
026 List<Name> namespaceNameSegments = namespaceFqName.pathSegments();
027 assert fullNameSegments.subList(0, namespaceNameSegments.size()).equals(namespaceNameSegments);
028 List<Name> relativeNameSegments = fullNameSegments.subList(namespaceNameSegments.size(), fullNameSegments.size());
029 return new ClassId(namespaceFqName, FqNameUnsafe.fromSegments(relativeNameSegments));
030 }
031
032 public ClassId(@NotNull FqName packageFqName, @NotNull FqNameUnsafe relativeClassName) {
033 this.packageFqName = packageFqName;
034 assert !relativeClassName.isRoot() : "Class name must not be root. " + packageFqName;
035 this.relativeClassName = relativeClassName;
036 }
037
038 @NotNull
039 public FqName getPackageFqName() {
040 return packageFqName;
041 }
042
043 @NotNull
044 public FqNameUnsafe getRelativeClassName() {
045 return relativeClassName;
046 }
047
048 @NotNull
049 public ClassId createNestedClassId(@NotNull Name name) {
050 return new ClassId(getPackageFqName(), relativeClassName.child(name));
051 }
052
053 @NotNull
054 public ClassId getOuterClassId() {
055 return new ClassId(getPackageFqName(), relativeClassName.parent());
056 }
057
058 public boolean isTopLevelClass() {
059 return relativeClassName.parent().isRoot();
060 }
061
062 public FqNameUnsafe asSingleFqName() {
063 if (packageFqName.isRoot()) return relativeClassName;
064 return new FqNameUnsafe(packageFqName.asString() + "." + relativeClassName.asString());
065 }
066
067 @Override
068 public boolean equals(Object o) {
069 if (this == o) return true;
070 if (o == null || getClass() != o.getClass()) return false;
071
072 ClassId id = (ClassId) o;
073
074 if (!packageFqName.equals(id.packageFqName)) return false;
075 if (!relativeClassName.equals(id.relativeClassName)) return false;
076
077 return true;
078 }
079
080 @Override
081 public int hashCode() {
082 int result = packageFqName.hashCode();
083 result = 31 * result + relativeClassName.hashCode();
084 return result;
085 }
086
087 @Override
088 public String toString() {
089 if (packageFqName.isRoot()) return "/" + relativeClassName;
090 return packageFqName.toString().replace('.', '/') + "/" + relativeClassName;
091 }
092 }