package net.onedaybeard.dominatrix.artemis;
import com.artemis.Component;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonValue;
/**
* A factory for extracting JSON serialized components by entity type.
* <p/>
* The factory performs internal caching of json data.
* @param <T>
*/
public final class JsonComponentFactory
{
public static final String TAG = JsonComponentFactory.class.getSimpleName();
private JsonValue jsonData;
private final String componentPackage;
private final Json json;
JsonComponentFactory(JsonValue jsonData, String componentPackage)
{
json = new Json();
this.jsonData = jsonData;
this.componentPackage = componentPackage;
}
public static FactoryInstance from(FileHandle file, String componentPackageName)
{
return new FileHandleCacher(file, componentPackageName);
}
public static FactoryInstance from(String json, String componentPackageName)
{
return new UncachedJsonContents(json, componentPackageName);
}
private Component getComponent(String entity, Class<?> component)
{
return (Component)json.readValue(component.getSimpleName(), component,
jsonDataForKeyPath(entity + ".components", this.jsonData));
}
public Array<Component> getComponents(String entityName)
{
Array<Component> components = new Array<Component>();
Array<Class<?>> componentTypes = getComponentTypes(entityName);
for (int i = 0, s = componentTypes.size; s > i; i++)
{
components.add(getComponent(entityName, componentTypes.get(i)));
}
return components;
}
Array<Component> getComponents(JsonValue data) throws ClassNotFoundException
{
JsonValue componentData = data.get("components");
Array<Component> components = new Array<Component>();
for (JsonValue entry = componentData.child(); entry != null; entry = entry.next())
{
String componentName = entry.name();
Class<?> componentClass = Class.forName(componentPackage + "." + componentName);
Object value = json.fromJson(componentClass, entry.toString());
components.add((Component)value);
}
return components;
}
private Array<Class<?>> getComponentTypes(String entityType)
{
Array<String> types = getKeys(entityType + ".components");
Array<Class<?>> components = new Array<Class<?>>(false, types.size);
for (int i = 0, s = types.size; s > i; i++)
{
try
{
Class<?> component = Class.forName(componentPackage + "." + types.get(i));
components.add(component);
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
}
return components;
}
public Array<String> getEntityTypes()
{
return getKeys(".");
}
public Array<JsonValue> getArray(String path)
{
try
{
JsonValue jsonData = jsonDataForKeyPath(path, this.jsonData);
Array<JsonValue> children = new Array<JsonValue>();
for (JsonValue child = jsonData.child(); child != null; child = child.next())
{
children.add(child);
}
return children;
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
private Array<String> getKeys(String path)
{
JsonValue data = jsonDataForKeyPath(path, jsonData);
Array<String> keys = new Array<String>();
for (JsonValue key = data.child(); key != null; key = key.next())
{
keys.add(key.name());
}
return keys;
}
private static JsonValue jsonDataForKeyPath(String path, JsonValue jsonData)
{
if (path.equals(".")) return jsonData;
String[] keys = path.split("\\.");
JsonValue data = jsonData;
for (int i = 0; i<keys.length - 1; i++)
{
if (data == null)
break;
data = data.getChild(keys[i]);
}
if (data == null || !data.name().equals(keys[keys.length - 1]))
throw new RuntimeException("Unable to find " + path);
return data;
}
public interface FactoryInstance
{
Array<Component> getComponents(String entityType);
Array<Component> getComponents(JsonValue data);
Array<String> getEntityTypes();
Array<JsonValue> getArray(String path);
}
}