package org.mutabilitydetector.locations;
/*
* #%L
* MutabilityDetector
* %%
* Copyright (C) 2008 - 2014 Graham Allan
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
public abstract class CodeLocation<T extends CodeLocation<T>> implements Comparable<T> {
private CodeLocation() {}
public abstract String typeName();
public abstract String prettyPrint();
@Immutable
public final static class UnknownCodeLocation extends CodeLocation<UnknownCodeLocation> {
public static final UnknownCodeLocation UNKNOWN = new UnknownCodeLocation();
private UnknownCodeLocation() { }
@Override
public int compareTo(@Nonnull UnknownCodeLocation o) {
return 0; // There can be only one.
}
@Override
public boolean equals(Object obj) {
return obj == this;
}
@Override
public int hashCode() {
return 0;
}
@Override
public String typeName() {
return "unknown code location";
}
@Override
public String prettyPrint() {
return "[Unknown code location]";
}
}
@Immutable
public static final class ClassLocation extends CodeLocation<ClassLocation> {
private final @Nonnull
String dottedClassName;
public ClassLocation(String dottedClassName) {
this.dottedClassName = dottedClassName;
}
@Override
public String typeName() {
return dottedClassName;
}
@Override
public int compareTo(@Nonnull ClassLocation other) {
return typeName().compareTo(other.typeName());
}
@Override
public int hashCode() {
return dottedClassName.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) { return true; }
if (obj == null) { return false; }
if (getClass() != obj.getClass()) { return false; }
ClassLocation other = (ClassLocation) obj;
return dottedClassName.equals(other.dottedClassName);
}
public static ClassLocation fromInternalName(String internalClassName) {
String dottedClassName = new ClassNameConverter().dotted(internalClassName);
return new ClassLocation(dottedClassName);
}
public static ClassLocation from(Slashed slashed) {
String dottedClassName = ClassIdentifier.forClass(slashed).asDotted().asString();
return new ClassLocation(dottedClassName);
}
public static ClassLocation from(Dotted dotted) {
return new ClassLocation(dotted.asString());
}
@Override
public String prettyPrint() {
return String.format("[Class: %s]", typeName());
}
}
@Immutable
public static final class FieldLocation extends CodeLocation<FieldLocation> {
private final @Nonnull String fieldName;
private final @Nonnull ClassLocation ownerOfField;
private FieldLocation(String fieldName, ClassLocation ownerOfField) {
this.fieldName = fieldName;
this.ownerOfField = ownerOfField;
}
public static FieldLocation fieldLocation(String fieldName, ClassLocation ownerOfField) {
return new FieldLocation(fieldName, ownerOfField);
}
public String fieldName() {
return fieldName;
}
@Override
public String typeName() {
return ownerOfField.typeName();
}
@Override
public int compareTo(@Nonnull FieldLocation other) {
int comparingOwner = ownerOfField.compareTo(other.ownerOfField);
int comparingFieldName = fieldName.compareTo(other.fieldName);
return comparingOwner == 0 ? comparingFieldName : comparingOwner;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + fieldName.hashCode();
result = prime * result + ownerOfField.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
FieldLocation other = (FieldLocation) obj;
return fieldName.equals(other.fieldName) && ownerOfField.equals(other.ownerOfField);
}
@Override
public String prettyPrint() {
return String.format("[Field: %s, Class: %s]", fieldName(), typeName());
}
}
}