Package com.forgeessentials.data

Source Code of com.forgeessentials.data.StorageManager

package com.forgeessentials.data;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;

import org.apache.commons.lang3.StringUtils;

import com.forgeessentials.data.api.ClassContainer;
import com.forgeessentials.data.api.DataStorageManager;
import com.forgeessentials.data.api.EnumDriverType;
import com.forgeessentials.data.api.IDataDriver;
import com.forgeessentials.data.api.IStorageManager;
import com.forgeessentials.data.api.ITypeInfo;
import com.forgeessentials.data.api.SaveableObject;
import com.forgeessentials.data.api.TypeData;
import com.forgeessentials.data.typeInfo.TypeInfoArray;
import com.forgeessentials.data.typeInfo.TypeInfoList;
import com.forgeessentials.data.typeInfo.TypeInfoMap;
import com.forgeessentials.data.typeInfo.TypeInfoSerialize;
import com.forgeessentials.data.typeInfo.TypeInfoSet;
import com.forgeessentials.data.typeInfo.TypeInfoStandard;
import com.forgeessentials.util.DBConnector;
import com.forgeessentials.util.OutputHandler;
import com.google.common.base.Throwables;

import cpw.mods.fml.common.event.FMLServerStartingEvent;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class StorageManager implements IStorageManager {

    public static final EnumDriverType defaultDriver = EnumDriverType.TEXT;
   
    private Configuration config;
    private EnumDriverType chosen = defaultDriver;
   
    // the defaults...
    private ConcurrentHashMap<EnumDriverType, String> typeChosens = new ConcurrentHashMap<EnumDriverType, String>();
   
    // registered ones...
    private ConcurrentHashMap<String, Class<? extends AbstractDataDriver>> classMap = new ConcurrentHashMap<String, Class<? extends AbstractDataDriver>>();

    // instantiated ones
    private ConcurrentHashMap<String, AbstractDataDriver> instanceMap = new ConcurrentHashMap<String, AbstractDataDriver>();
   
    private ConcurrentHashMap<String, ITypeInfo> taggerList = new ConcurrentHashMap<String, ITypeInfo>();

    public StorageManager(Configuration config)
    {
        this.config = config;

        config.addCustomCategoryComment("Data", "Configuration options for how ForgeEssentials will save its data for persistence between sessions.");

        // generates the configs...
        Property prop = config.get("Data", "storageType", defaultDriver.toString());
        prop.comment = "Specifies the variety of data storage FE will use. Options: " + StringUtils.join(EnumDriverType.values(), ", ");
        chosen = EnumDriverType.valueOf(prop.getString());

        typeChosens.put(EnumDriverType.TEXT, "ForgeConfig");
        typeChosens.put(EnumDriverType.BINARY, "NBT");
        typeChosens.put(EnumDriverType.SQL, "SQL_DB");

        String cat;
        for (EnumDriverType type : EnumDriverType.values())
        {
            if (type == EnumDriverType.SQL)
            {
                continue;
            }
            cat = "Data." + type;
            prop = config.get(cat, "chosenDriver", typeChosens.get(type));
            typeChosens.put(type, prop.getString());
        }
    }

    /**
     * Parses the ForgeEssentials config file and determines which Driver to
     * use. This will be loaded up with the lazy method. only the chosen ones
     * will be loaded...
     *
     * @param Config
     */
    public void setupManager()
    {
        // verify default driver...
        if (classMap.get(typeChosens.get(defaultDriver)) == null)
        {
            throw new RuntimeException("{ForgeEssentials} Default DataDriver is invalid! Valid types: " + Arrays.toString(classMap.values().toArray()));
        }

        for (Entry<String, AbstractDataDriver> entry : instanceMap.entrySet())
        {
            try
            {
                // things MAY error here as well...
                entry.getValue().parseConfigs(config, "Data." + entry.getValue().getType() + "." + entry.getValue().getName());
            }
            catch (Exception e)
            {
                OutputHandler.felog.info("Problem loading DataDriver " + entry.getKey());
                OutputHandler.felog.info("ForgeEssentials will not be able to save any data through this driver");
                e.printStackTrace();
            }
        }
    }

    /**
     * Passes the ServerStart event to the dataDrivers
     */
    public void serverStart(FMLServerStartingEvent event)
    {
        for (IDataDriver driver : instanceMap.values())
        {
            // things MAY error here as well...
            driver.serverStart(event);
        }
    }

    /**
     * Should only be done before the server starts. May override existing
     * Driver types.
     *
     * @param name Name to be used in configs
     * @param c
     */
    @Override
    public void registerDriver(String name, Class<? extends AbstractDataDriver> c)
    {
        try
        {
            // If there is a problem constructing the driver, this line will
            // fail and we will enter the catch block.
            AbstractDataDriver driver = c.newInstance();
            classMap.put(name, c);
            instanceMap.put(name, driver);
        }
        catch (Exception e)
        {
            OutputHandler.felog.info("Problem initializing DataDriver " + name);
            OutputHandler.felog.info("ForgeEssentials will not be able to save any data through this driver");
            e.printStackTrace();
        }
    }

    @Override
    public AbstractDataDriver getReccomendedDriver()
    {
        return getDriverOfType(chosen);
    }

    @Override
    public AbstractDataDriver getDriverOfType(EnumDriverType type)
    {
        return getDriverOfName(typeChosens.get(type));
    }

    /**
     * @param name
     * @return default DataDriver if the requested one is unavailable.
     */
    private AbstractDataDriver getDriverOfName(String name)
    {
        AbstractDataDriver d = instanceMap.get(name);
        if (d == null)
        {
            d = instanceMap.get(defaultDriver);
        }
        return d;
    }

    @Override
    public void registerSaveableClass(ClassContainer type)
    {
        ITypeInfo info = null;

        if (type.isArray() && !type.getType().getComponentType().isPrimitive() && !String.class.isAssignableFrom(type.getType().getComponentType()))
        {
            info = new TypeInfoArray(new ClassContainer(type.getType()));
        }
        else if (Map.class.isAssignableFrom(type.getType()))
        {
            info = new TypeInfoMap(type);
        }
        else if (Set.class.isAssignableFrom(type.getType()))
        {
            info = new TypeInfoSet(type);
        }
        else if (List.class.isAssignableFrom(type.getType()))
        {
            info = new TypeInfoList(type);
        }
        else if (type.getType().isAnnotationPresent(SaveableObject.class))
        {
            info = new TypeInfoStandard(type.getType());
        }
        else if (Serializable.class.isAssignableFrom(type.getType()))
        {
            info = new TypeInfoSerialize(type);
        }

        if (info == null)
        {
            return;
        }

        info.build();
        taggerList.put(type.toString(), info);
    }

    @Override
    public void registerSaveableClass(Class<? extends ITypeInfo> infoType, ClassContainer type)
    {
        if (infoType.equals(TypeInfoStandard.class))
        {
            registerSaveableClass(type);
        }
        else
        {
            try
            {
                Constructor[] constructors = infoType.getConstructors();
                Constructor<? extends ITypeInfo> con = null;

                int arg = -1;

                for (Constructor c : constructors)
                {
                    if (c.getParameterTypes().length == 0)
                    {
                        con = c;
                        arg = 0;
                        break;
                    }

                    if (c.getParameterTypes().length == 1)
                    {
                        if (c.getParameterTypes()[0].equals(ClassContainer.class))
                        {
                            con = c;
                            arg = 2;
                            break;
                        }

                        if (c.getParameterTypes()[0].equals(Class.class))
                        {
                            con = c;
                            arg = 1;
                            break;
                        }
                    }
                }

                ITypeInfo created = null;

                if (con == null)
                {
                    throw new IllegalArgumentException(infoType.getCanonicalName() + " must have useable constructors! See the ITypeInfo documentation!");
                }

                switch (arg)
                {
                case 0:
                    created = con.newInstance();
                    break;
                case 1:
                    created = con.newInstance(type.getType());
                    break;
                case 2:
                    created = con.newInstance(type);
                    break;
                }

                created.build();
                taggerList.put(type.toString(), created);
            }
            catch (SecurityException e)
            {
                OutputHandler.felog.severe(infoType.getCanonicalName() + " must have useable constructors! See the ITypeInfo documentation!");
                Throwables.propagate(e);
            }
            catch (InstantiationException e)
            {
                OutputHandler.felog.severe(infoType.getCanonicalName() + " must have useable constructors! See the ITypeInfo documentation!");
                Throwables.propagate(e);
            }
            catch (IllegalAccessException e)
            {
                OutputHandler.felog.severe(infoType.getCanonicalName() + " must have useable constructors! See the ITypeInfo documentation!");
                Throwables.propagate(e);
            }
            catch (IllegalArgumentException e)
            {
                OutputHandler.felog.severe(infoType.getCanonicalName() + " must have useable constructors! See the ITypeInfo documentation!");
                Throwables.propagate(e);
            }
            catch (InvocationTargetException e)
            {
                OutputHandler.felog.severe(infoType.getCanonicalName() + " must have useable constructors! See the ITypeInfo documentation!");
                Throwables.propagate(e);
            }
        }
    }

    public boolean isClassRegisterred(ClassContainer type)
    {
        if (type == null)
        {
            return false;
        }
        return taggerList.containsKey(type.toString());
    }

    @Override
    public ITypeInfo getInfoForType(ClassContainer type)
    {
        ITypeInfo tagged = taggerList.get(type.toString());

        if (tagged != null)
        {
            return tagged;
        }

        ClassContainer tempType = type;

        while (!isClassRegisterred(tempType))
        {
            if (tempType == null)
            {
                break;
            }
            else if (tempType.hasParameters())
            {
                tempType = new ClassContainer(tempType.getType());
            }
            else if (tempType.getType().getSuperclass() != null)
            {
                tempType = new ClassContainer(tempType.getType().getSuperclass(), type.getParameters());
            }
            else if (tempType.getType().getSuperclass() == null)
            {
                tempType = null;
            }
        }

        if (tempType == null)
        {
            for (Class inter : type.getType().getInterfaces())
            {
                tempType = new ClassContainer(inter, type.getParameters());

                if (isClassRegisterred(tempType))
                {
                    break;
                }

                tempType = new ClassContainer(inter);

                if (isClassRegisterred(tempType))
                {
                    break;
                }

                tempType = null;
            }
        }

        if (tempType == null)
        {
            registerSaveableClass(type);
            tagged = taggerList.get(type.toString());
            return tagged;
        }

        return taggerList.get(tempType.toString());
    }

    @Override
    public DBConnector getCoreDBConnector()
    {
        return ((SQLDataDriver) getDriverOfType(EnumDriverType.SQL)).connector;
    }

    @Override
    public TypeData getDataForType(ClassContainer type)
    {
        return new TypeData(type);
    }

    @Override
    public TypeData getDataForObject(ClassContainer container, Object obj)
    {
        ITypeInfo info = getInfoForType(container);
        TypeData data = info.getTypeDataFromObject(obj);

        ITypeInfo tempInfo;
        for (Entry<String, Object> e : data.getAllFields())
        {
            if (e.getValue() != null && !(e.getValue() instanceof TypeData) && StorageManager.isTypeComplex(e.getValue().getClass()))
            {
                tempInfo = info.getInfoForField(e.getKey());
                data.putField(e.getKey(), DataStorageManager.getDataForObject(tempInfo.getTypeOfField(e.getKey()), e.getValue()));
            }
        }

        return data;
    }

    /**
     * @param t class check
     * @return True if TypeTagger must create a nested TaggedClass to allow DataDrivers to correctly save this type of object.
     */
    public static boolean isTypeComplex(Class type)
    {
        boolean flag = true;
        if (type.isPrimitive() || type.equals(Integer.class) || type.equals(Float.class) ||
                type.equals(Double.class) || type.equals(Boolean.class) || type.equals(String.class) ||
                type.equals(Byte.class) || type.equals(Long.class))
        {
            flag = false;
        }
        else if (type.isArray())
        {
            return !(type.getComponentType().isPrimitive() || type.getComponentType().equals(Integer.class) || type.getComponentType().equals(Float.class) ||
                    type.getComponentType().equals(Double.class) || type.getComponentType().equals(Boolean.class) || type.getComponentType()
                    .equals(String.class) || type.equals(Byte.class));
        }

        return flag;
    }

    /**
     * @param t class check
     * @return True if TypeTagger must create a nested TaggedClass to allow DataDrivers to correctly save this type of object.
     */
    public static boolean isTypeComplex(ClassContainer type)
    {
        if (type.hasParameters())
        {
            return true;
        }
        else
        {
            return isTypeComplex(type.getType());
        }
    }
}
TOP

Related Classes of com.forgeessentials.data.StorageManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.