package com.github.niwaniwa.we.core.player;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import org.bukkit.Bukkit;
import org.bukkit.entity.Player;

import com.github.niwaniwa.we.core.WhiteEggCore;

/**
 * WhitePlayerのfactoryクラス
 * @author niwaniwa
 *
 */
public class WhitePlayerFactory {

	/**
	 * instance化不可
	 */
	private WhitePlayerFactory(){}

	private static final List<WhitePlayer> players = new ArrayList<>();

	/**
	 * プレイヤーのインスタンスを返します
	 * @param player プレイヤー
	 * @return プレイヤー
	 */
	public static WhitePlayer newInstance(Player player){
		for(WhitePlayer p : players){
			if(p.getUniqueId().equals(player.getUniqueId())){ return p; }
		}
		WhitePlayer white = new WhiteEggPlayer(player);
		white.load();
		players.add(white);
		return white;
	}

	/**
	 * instance
	 * @param <T> WhitePlayerを継承したクラス
	 * @param clazz 取得するクラス
	 * @param player プレイヤー
	 * @return T 指定したクラスのinstance
	 */
	public static <T extends WhitePlayer> T newInstance(Player player, Class<T> clazz){
		if(clazz.isInterface()){ return null; }
		if(Modifier.isAbstract(clazz.getModifiers())){ return null; }
		T instance = null;
		try {
			Constructor<T> c = clazz.getConstructor(Player.class);
			instance = c.newInstance(player);
		} catch (Exception e){
		}
		if(instance == null){ return null; }
		instance.load();
		return instance;
	}

	/**
	 * 型を指定したクラスへ変換する
	 * @param <T> WhitePlayerを継承したクラス
	 * @param from 変換前のinstance
	 * @param to 変換後のクラス
	 * @return 指定したクラスのinstance(データ引き継ぎ)
	 */
	public static <T extends WhitePlayer> T cast(WhitePlayer from, Class<T> to){
		if(Modifier.isAbstract(to.getModifiers())
				|| from.getClass().getSimpleName().equals(to.getSimpleName())){
			return null;
		}
		from.save();
		T instance = null;
		try {
			instance = (T) to.getConstructor(Player.class).newInstance(from.getPlayer());
		} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
				| NoSuchMethodException | SecurityException e) {
		}
		instance.saveVariable(from.serialize().toString());
		return instance;
	}

	/**
	 * プレイヤーデータの保存
	 */
	public static void saveAll(){
		System.out.println("Saving players (WhiteEgg)");
		WhitePlayerFactory.getPlayers().forEach(p -> p.save());
	}

	/**
	 * プレイヤーデータの読み込み
	 */
	public static void load(){
		if(Bukkit.getOnlinePlayers().size() == 0){ return; }
		WhiteEggCore.getAPI().getOnlinePlayers().forEach(p -> p.reload());
	}

	/**
	 * サーバー起動時から取得時までに生成されたプレイヤーのインスタンスの取得
	 * @return instance
	 */
	public static List<WhitePlayer> getPlayers(){
		return players;
	}

}

@@ -269,24 +269,68 @@
 tity.Player;
+%0Aimport org.bukkit.scheduler.BukkitRunnable;
 %0A%0Aimport com
@@ -588,16 +588,56 @@
 ist%3C%3E();
+%0A%09private static boolean isLock = false;
 %0A%0A%09/**%0A%09
@@ -759,16 +759,106 @@
 layer)%7B%0A
+%09%09if(isLock)%7B throw new IllegalStateException(%22Cannot use newInstance for data load.%22); %7D%0A
 %09%09for(Wh
@@ -1312,83 +1312,216 @@
 ))%7B 
-return null; %7D%0A%09%09if(Modifier.isAbstract(clazz.getModifiers()))%7B return null
+throw new IllegalArgumentException(clazz.getSimpleName() + %22 is Interface%22); %7D%0A%09%09if(Modifier.isAbstract(clazz.getModifiers()))%7B throw new IllegalArgumentException(clazz.getSimpleName() + %22 is Abstract class%22)
 ; %7D%0A
@@ -2100,27 +2100,133 @@
 )))%7B%0A%09%09%09
-return null
+throw new IllegalArgumentException(to.getSimpleName() + %22 is Abstract class or Same as '%22 + to.getSimpleName() + %22'%22)
 ;%0A%09%09%7D%0A%09%09
@@ -2883,70 +2883,230 @@
 %7D%0A%09%09
-WhiteEggCore.getAPI().getOnlinePlayers().forEach(p -%3E p.reload
+isLock = true;%0A%09%09new BukkitRunnable() %7B%0A%09%09%09@Override%0A%09%09%09public void run() %7B%0A%09%09%09%09WhiteEggCore.getAPI().getOnlinePlayers().forEach(p -%3E p.reload());%0A%09%09%09%09isLock = false;%0A%09%09%09%7D%0A%09%09%7D.runTaskAsynchronously(WhiteEggCore.getInstance
 ());

Change code