MapSchemaParserBack.java
package space.sunqian.fs.object.schema;
import space.sunqian.annotation.Nonnull;
import space.sunqian.fs.cache.SimpleCache;
import space.sunqian.fs.reflect.ReflectionException;
import space.sunqian.fs.reflect.TypeKit;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
final class MapSchemaParserBack {
static @Nonnull MapSchemaParser defaultParser() {
return DefaultMapSchemaParser.INST;
}
static @Nonnull MapSchemaParser defaultCachedParser() {
return CachedMapSchemaParser.DEFAULT;
}
static @Nonnull MapSchemaParserBack.CachedMapSchemaParser newCachedParser(
@Nonnull SimpleCache<@Nonnull Type, @Nonnull MapSchema> cache,
@Nonnull MapSchemaParser parser
) {
return new CachedMapSchemaParser(cache, parser);
}
private enum DefaultMapSchemaParser implements MapSchemaParser {
INST;
@Override
public @Nonnull MapSchema parse(@Nonnull Type type) throws DataSchemaException {
try {
return new MapSchemaImpl(type);
} catch (Exception e) {
throw new DataSchemaException(e);
}
}
private final class MapSchemaImpl implements MapSchema {
private final @Nonnull Type type;
private final @Nonnull Type keyType;
private final @Nonnull Type valueType;
private MapSchemaImpl(@Nonnull Type type) throws ReflectionException {
if (type instanceof MapType) {
@SuppressWarnings("PatternVariableCanBeUsed")
MapType mapType = (MapType) type;
this.type = mapType.mapType();
this.keyType = mapType.keyType();
this.valueType = mapType.valueType();
} else {
this.type = type;
List<Type> actualTypes = TypeKit.resolveActualTypeArguments(type, Map.class);
this.keyType = actualTypes.get(0);
this.valueType = actualTypes.get(1);
}
}
@Override
public @Nonnull Type type() {
return type;
}
@Override
public @Nonnull MapSchemaParser parser() {
return DefaultMapSchemaParser.this;
}
@Override
public @Nonnull Type keyType() {
return keyType;
}
@Override
public @Nonnull Type valueType() {
return valueType;
}
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
@Override
public boolean equals(Object o) {
return SchemaKit.equals(this, o);
}
@Override
public int hashCode() {
return SchemaKit.hashCode(this);
}
@Override
public @Nonnull String toString() {
return SchemaKit.toString(this);
}
}
}
private static final class CachedMapSchemaParser implements MapSchemaParser {
private static final @Nonnull MapSchemaParserBack.CachedMapSchemaParser DEFAULT = newCachedParser(
SimpleCache.ofSoft(),
MapSchemaParser.defaultParser()
);
private final @Nonnull SimpleCache<@Nonnull Type, @Nonnull MapSchema> cache;
private final @Nonnull MapSchemaParser parser;
private CachedMapSchemaParser(
@Nonnull SimpleCache<@Nonnull Type, @Nonnull MapSchema> cache,
@Nonnull MapSchemaParser parser
) {
this.cache = cache;
this.parser = parser;
}
@Override
public @Nonnull MapSchema parse(@Nonnull Type type) {
return cache.get(type, parser::parse);
}
}
private MapSchemaParserBack() {
}
}