com.xiovr.unibot.bot.impl.BotGameConfigImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.xiovr.unibot.bot.impl.BotGameConfigImpl.java

Source

/**
 * Copyright (c) 2014 xio4
 * Universal bot for lineage-like games (Archeage, Lineage2 etc)
 *
 * This file is part of Unibot.
 *
 * Unibot is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.xiovr.unibot.bot.impl;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.xiovr.unibot.bot.BotGameConfig;
import com.xiovr.unibot.bot.Param;
import com.xiovr.unibot.bot.Settings;
import com.xiovr.unibot.utils.BotUtils;
import com.xiovr.unibot.utils.SortedProperties;

@Component
public class BotGameConfigImpl implements BotGameConfig {
    private static final Logger logger = LoggerFactory.getLogger(BotGameConfigImpl.class);
    private String absDirPath;

    public BotGameConfigImpl() {
        super();

        absDirPath = new File("").getAbsolutePath();
    }

    private Properties createSettings(Class<?> clazz, String fn, String comment) {

        Properties props = new SortedProperties();
        try {
            //         File file = new File("/" + DIR_PATH + "/" + fn);
            File file = new File(fn);
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                // Find setters
                if (method.getName().startsWith("set")) {
                    if (method.isAnnotationPresent(Param.class)) {
                        Annotation annotation = method.getAnnotation(Param.class);
                        Param param = (Param) annotation;
                        if (param.name().equals("") || param.values().length == 0) {
                            throw new RuntimeException("Wrong param in class " + clazz.getCanonicalName()
                                    + " with method " + method.getName());
                        }
                        Class<?>[] paramClazzes = method.getParameterTypes();
                        if (paramClazzes.length != 1) {
                            throw new RuntimeException("Error contract design in class " + clazz.getCanonicalName()
                                    + " with method " + method.getName());
                        }
                        // Check param belongs to List
                        Class<?> paramClazz = paramClazzes[0];
                        if (List.class.isAssignableFrom(paramClazz)) {
                            // Oh, its array...
                            // May be its InetSocketAddress?
                            Type[] gpt = method.getGenericParameterTypes();
                            if (gpt[0] instanceof ParameterizedType) {
                                ParameterizedType type = (ParameterizedType) gpt[0];
                                Type[] typeArguments = type.getActualTypeArguments();

                                for (Type typeArgument : typeArguments) {
                                    Class<?> classType = ((Class<?>) typeArgument);
                                    if (InetSocketAddress.class.isAssignableFrom(classType)) {
                                        String[] vals = param.values();
                                        for (int i = 0; i < vals.length / 2; ++i) {
                                            props.setProperty(param.name() + "." + String.valueOf(i) + ".ip",
                                                    vals[i * 2]);
                                            props.setProperty(param.name() + "." + String.valueOf(i) + ".port",
                                                    vals[i * 2 + 1]);
                                        }
                                        props.setProperty(param.name() + ".count", String.valueOf(vals.length / 2));

                                    } else {
                                        throw new RuntimeException("Settings param in class "
                                                + clazz.getCanonicalName() + " with method " + method.getName()
                                                + " not implementes yet");
                                    }
                                }

                            }
                        } else if (paramClazz.isPrimitive()) {
                            props.setProperty(param.name(), param.values()[0]);

                        } else if (String.class.isAssignableFrom(paramClazz)) {

                            props.setProperty(param.name(), param.values()[0]);

                        } else {
                            throw new RuntimeException("Settings param in class " + clazz.getCanonicalName()
                                    + " with method " + method.getName() + " not implemented yet");
                        }

                    }
                }
            }

            BotUtils.saveProperties(file, props, comment);
        } catch (IOException e) {
            logger.error("Error save file " + fn);
        }
        return props;
    }

    @Override
    // public void loadSettings(Settings instance, Class<?> clazz, String fn)
    public void loadSettings(Settings instance, String fn) {

        Class<?> clazz = instance.getClass().getInterfaces()[0];
        //      File file = new File("/" + DIR_PATH + "/" + fn);
        File file = new File(fn);
        Properties props = null;
        try {
            props = BotUtils.loadProperties(file);

            // botEnvironment.setClientIp((props.getProperty("client.ip",
            // "127.0.0.1"));
        } catch (IOException e) {
            // e.printStackTrace();
            //         logger.warn("Can't load settings /" + DIR_PATH + "/" + fn
            //               + ". Create new settings file.");
            logger.warn("Can't load settings " + fn + ". Create new settings file.");
            props = createSettings(clazz, fn, "Bot v" + VERSION);

        }
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            // Find setters
            if (method.getName().startsWith("set")) {

                if (method.isAnnotationPresent(Param.class)) {

                    Annotation annotation = method.getAnnotation(Param.class);
                    Param param = (Param) annotation;
                    if (param.name().equals("") || param.values().length == 0) {
                        throw new RuntimeException("Wrong param in class " + clazz.getCanonicalName()
                                + " with method " + method.getName());
                    }
                    Class<?>[] paramClazzes = method.getParameterTypes();
                    if (paramClazzes.length != 1) {
                        throw new RuntimeException("Error contract design in class " + clazz.getCanonicalName()
                                + " with method " + method.getName());
                    }
                    // Check param belongs to List
                    Class<?> paramClazz = paramClazzes[0];

                    try {
                        if (List.class.isAssignableFrom(paramClazz)) {
                            // Oh, its array...
                            // May be its InetSocketAddress?

                            Type[] gpt = method.getGenericParameterTypes();
                            if (gpt[0] instanceof ParameterizedType) {
                                ParameterizedType type = (ParameterizedType) gpt[0];
                                Type[] typeArguments = type.getActualTypeArguments();

                                for (Type typeArgument : typeArguments) {
                                    Class<?> classType = ((Class<?>) typeArgument);
                                    if (InetSocketAddress.class.isAssignableFrom(classType)) {
                                        List<InetSocketAddress> isaArr = new ArrayList<>();
                                        int cnt = Integer.parseInt(props.getProperty(param.name() + ".count", "2"));
                                        for (int i = 0; i < cnt; ++i) {
                                            String defaultHostname = "";
                                            String defaultPort = "";
                                            if (param.values().length > i * 2) {
                                                defaultHostname = param.values()[i * 2];
                                                defaultPort = param.values()[i * 2 + 1];
                                            } else {
                                                defaultHostname = DEFAULT_HOSTNAME;
                                                defaultPort = String.valueOf(DEFAULT_PORT);
                                            }
                                            InetSocketAddress isa = new InetSocketAddress(
                                                    props.getProperty(
                                                            param.name() + "." + String.valueOf(i) + ".ip",
                                                            defaultHostname),
                                                    Integer.parseInt(props.getProperty(
                                                            param.name() + "." + String.valueOf(i) + ".port",
                                                            defaultPort)));
                                            // invocableClazz.getMethod(method.getName(),
                                            // InetSocketAddress.class).invoke(
                                            // instance, isa);
                                            isaArr.add(isa);

                                        }

                                        method.invoke(instance, isaArr);

                                    } else {
                                        throw new RuntimeException("Settings param in class "
                                                + clazz.getCanonicalName() + " with method " + method.getName()
                                                + " not implemented yet");
                                    }
                                }

                            }
                        } else if (paramClazz.isPrimitive()) {
                            if (int.class.isAssignableFrom(paramClazz)) {
                                method.invoke(instance,
                                        Integer.parseInt(props.getProperty(param.name(), param.values()[0])));
                            } else if (long.class.isAssignableFrom(paramClazz)) {
                                method.invoke(instance,
                                        Long.parseLong(props.getProperty(param.name(), param.values()[0])));
                            } else if (boolean.class.isAssignableFrom(paramClazz)) {
                                method.invoke(instance,
                                        Boolean.parseBoolean(props.getProperty(param.name(), param.values()[0])));
                            } else if (double.class.isAssignableFrom(paramClazz)) {
                                method.invoke(instance,
                                        Double.parseDouble(props.getProperty(param.name(), param.values()[0])));
                            }

                        } else if (String.class.isAssignableFrom(paramClazz)) {
                            method.invoke(instance, props.getProperty(param.name(), param.values()[0]));
                        } else {
                            throw new RuntimeException("Settings param in class " + clazz.getCanonicalName()
                                    + " with method " + method.getName() + " not implemented yet");
                        }
                    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void saveSettings(Settings instance, String fn, String comment) {
        Class<?> clazz = instance.getClass().getInterfaces()[0];
        Class<?> invocableClazz = instance.getClass();
        //      File file = new File("/" + DIR_PATH + "/" + fn);
        File file = new File(fn);
        Properties props = new SortedProperties();

        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            // Find setters
            if (method.getName().startsWith("set")) {

                if (method.isAnnotationPresent(Param.class)) {

                    Annotation annotation = method.getAnnotation(Param.class);
                    Param param = (Param) annotation;
                    if (param.name().equals("") || param.values().length == 0) {
                        throw new RuntimeException("Wrong param in class " + clazz.getCanonicalName()
                                + " with method " + method.getName());
                    }
                    Class<?>[] paramClazzes = method.getParameterTypes();
                    if (paramClazzes.length != 1) {
                        throw new RuntimeException("Error contract design in class " + clazz.getCanonicalName()
                                + " with method " + method.getName());
                    }
                    // Check param belongs to List
                    Class<?> paramClazz = paramClazzes[0];

                    try {
                        if (List.class.isAssignableFrom(paramClazz)) {
                            // Oh, its array...
                            // May be its InetSocketAddress?

                            Type[] gpt = method.getGenericParameterTypes();
                            if (gpt[0] instanceof ParameterizedType) {
                                ParameterizedType type = (ParameterizedType) gpt[0];
                                Type[] typeArguments = type.getActualTypeArguments();

                                for (Type typeArgument : typeArguments) {
                                    Class<?> classType = ((Class<?>) typeArgument);
                                    if (InetSocketAddress.class.isAssignableFrom(classType)) {
                                        List<InetSocketAddress> isaArr = (List<InetSocketAddress>) invocableClazz
                                                .getMethod("get" + method.getName().substring(3)).invoke(instance);
                                        int cnt = isaArr.size();
                                        props.setProperty(param.name() + ".count", String.valueOf(cnt));
                                        for (int i = 0; i < cnt; ++i) {
                                            props.setProperty(param.name() + "." + String.valueOf(i) + ".ip",
                                                    isaArr.get(i).getHostString());
                                            props.setProperty(param.name() + "." + String.valueOf(i) + ".port",
                                                    String.valueOf(isaArr.get(i).getPort()));
                                        }
                                    } else {
                                        throw new RuntimeException("Settings param in class "
                                                + clazz.getCanonicalName() + " with method " + method.getName()
                                                + " not implemented yet");
                                    }
                                }

                            }
                        } else if (paramClazz.isPrimitive()) {
                            props.setProperty(param.name(), String.valueOf(invocableClazz
                                    .getMethod("get" + method.getName().substring(3)).invoke(instance)));
                        } else if (String.class.isAssignableFrom(paramClazz)) {
                            props.setProperty(param.name(), (String) (invocableClazz
                                    .getMethod("get" + method.getName().substring(3)).invoke(instance)));
                        } else {
                            throw new RuntimeException("Settings param in class " + clazz.getCanonicalName()
                                    + " with method " + method.getName() + " not implemented yet");
                        }
                        BotUtils.saveProperties(file, props, "Bot v" + VERSION);
                    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
                            | NoSuchMethodException | IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    @Override
    public String getAbsDirPath() {
        return this.absDirPath;
    }
}