package org.bson.internal;
import org.bson.codecs.Codec;
import org.bson.codecs.configuration.CodecRegistry;
class ChildCodecRegistry<T> implements CodecRegistry {
private final ChildCodecRegistry<?> parent;
private final CycleDetectingCodecRegistry registry;
private final Class<T> codecClass;
ChildCodecRegistry(final CycleDetectingCodecRegistry registry, final Class<T> codecClass) {
this.codecClass = codecClass;
this.parent = null;
this.registry = registry;
}
private ChildCodecRegistry(final ChildCodecRegistry<?> parent, final Class<T> codecClass) {
this.parent = parent;
this.codecClass = codecClass;
this.registry = parent.registry;
}
public Class<T> getCodecClass() {
return codecClass;
}
public <U> Codec<U> get(final Class<U> clazz) {
if (hasCycles(clazz)) {
return new LazyCodec<U>(registry, clazz);
} else {
return registry.get(new ChildCodecRegistry<U>(this, clazz));
}
}
@SuppressWarnings("rawtypes")
private <U> Boolean hasCycles(final Class<U> theClass) {
ChildCodecRegistry current = this;
while (current != null) {
if (current.codecClass.equals(theClass)) {
return true;
}
current = current.parent;
}
return false;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ChildCodecRegistry<?> that = (ChildCodecRegistry) o;
if (!codecClass.equals(that.codecClass)) {
return false;
}
if (parent != null ? !parent.equals(that.parent) : that.parent != null) {
return false;
}
if (!registry.equals(that.registry)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = parent != null ? parent.hashCode() : 0;
result = 31 * result + registry.hashCode();
result = 31 * result + codecClass.hashCode();
return result;
}
}