package com.psddev.cms.db;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.psddev.dari.db.Database;
import com.psddev.dari.db.ObjectField;
import com.psddev.dari.db.ObjectType;
import com.psddev.dari.util.CodeUtils;
import com.psddev.dari.util.CompactMap;
import com.psddev.dari.util.Lazy;
import com.psddev.dari.util.ObjectUtils;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.HashSet;
import java.util.ListResourceBundle;
import java.util.Map;
import java.util.Set;
final class ObjectTypeResourceBundle extends ListResourceBundle {
private static final Lazy<ObjectTypeResourceBundle> GLOBAL_BUNDLE = new Lazy<ObjectTypeResourceBundle>() {
@Override
protected ObjectTypeResourceBundle create() {
return new ObjectTypeResourceBundle(null);
}
};
private static final LoadingCache<ObjectType, ObjectTypeResourceBundle> TYPE_BUNDLES = CacheBuilder
.newBuilder()
.weakKeys()
.build(new CacheLoader<ObjectType, ObjectTypeResourceBundle>() {
@Override
@ParametersAreNonnullByDefault
public ObjectTypeResourceBundle load(ObjectType type) {
return new ObjectTypeResourceBundle(type);
}
});
static {
CodeUtils.addRedefineClassesListener(classes -> {
GLOBAL_BUNDLE.reset();
classes.stream()
.map(ObjectType::getInstance)
.filter(type -> type != null)
.forEach(TYPE_BUNDLES::invalidate);
});
}
private final Map<String, Object> map;
private final Object[][] contents;
public static ObjectTypeResourceBundle getInstance(ObjectType type) {
return type != null
? TYPE_BUNDLES.getUnchecked(type)
: GLOBAL_BUNDLE.get();
}
public static void invalidateInstances() {
GLOBAL_BUNDLE.reset();
TYPE_BUNDLES.invalidateAll();
}
private ObjectTypeResourceBundle(ObjectType type) {
Map<String, Object> map = new CompactMap<>();
if (type != null) {
map.put("displayName", type.getDisplayName());
}
Set<String> tabs = new HashSet<>();
for (ObjectField field : type != null
? type.getFields()
: Database.Static.getDefault().getEnvironment().getFields()) {
String tab = field.as(ToolUi.class).getTab();
if (!ObjectUtils.isBlank(tab)) {
tabs.add(tab);
}
map.put("field." + field.getInternalName(), field.getDisplayName());
}
for (String tab : tabs) {
map.put("tab." + tab, tab);
}
map.put("tab.Main", "Main");
this.map = ImmutableMap.copyOf(map);
this.contents = map.entrySet().stream()
.map(entry -> new Object[] { entry.getKey(), entry.getValue() })
.toArray(Object[][]::new);
}
public Map<String, Object> getMap() {
return map;
}
@Override
protected Object[][] getContents() {
return contents;
}
}