package org.carbon.util.constructor;

import org.apache.commons.lang3.reflect.ConstructorUtils;
import org.carbon.util.exception.ConstructionException;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

/**
 * @author Shota Oda 2017/12/31.
 */
public class NoArgsConstructorUtil {
    public static boolean isInnerNoStaticClass(Class<?> type) {
        return type.isMemberClass() && !Modifier.isStatic(type.getModifiers());
    }

    public static <T> T construct(Class<T> type) throws ConstructionException {
        try {
            return ConstructorUtils.invokeExactConstructor(type);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
            throw new ConstructionException(type, e);
        }
    }

    public static <T> T construct(Class<T> type, Object enclosing) throws ConstructionException {
        assertInnerNoStaticArguments(type, enclosing);
        try {
            return ConstructorUtils.invokeExactConstructor(type, enclosing);
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            throw new ConstructionException(type, e);
        }
    }

    private static void assertInnerNoStaticArguments(Class<?> type, Object enclosing) throws ConstructionException {
        if (!isInnerNoStaticClass(type)) {
            IllegalArgumentException cause = new IllegalArgumentException(type + " is not inner no-static class");
            throw new ConstructionException(type, cause);
        }
        if (enclosing == null) {
            IllegalArgumentException cause = new IllegalArgumentException("class[" + type + "] is inner(no-static) class, but Enclosing class is not provided");
            throw new ConstructionException(type, cause);
        }
        Class<?> enclosingClass = type.getEnclosingClass();
        Class<?> parentClass = enclosing.getClass();
        if (!enclosingClass.equals(parentClass)) {
            IllegalArgumentException cause = new IllegalArgumentException("class[" + type + "] is inner(no-static) class, but Provide Enclosing Object(type[" + parentClass + "]) is not equal actual Enclosing class(" + enclosingClass + ")");
            throw new ConstructionException(type, cause);
        }
    }
}

@@ -341,32 +341,30 @@
 lean isInner
-NoStatic
+Member
 Class(Class%3C
@@ -931,32 +931,35 @@
 ertInner
-NoStatic
+MemberClass
 Argument
 s(type, 
@@ -950,17 +950,16 @@
 Argument
-s
 (type, e
@@ -1292,24 +1292,27 @@
 nner
-NoStatic
+MemberClass
 Argument
 s(Cl
@@ -1307,17 +1307,16 @@
 Argument
-s
 (Class%3C?
@@ -1396,16 +1396,14 @@
 nner
-NoStatic
+Member
 Clas

add utilities