// Path: src/main/java/com/michaelfotiadis/validator/annotated/SupportedAnnotationContainer.java
// public final class SupportedAnnotationContainer {
// 
//     private static final String PACKAGE_NAME = "com.michaelfotiadis.validator.annotated.annotations";
//     private static final List<Class> SUPPORTED_CLASSES = new ArrayList<>();
// 
//     private SupportedAnnotationContainer() {
//         // NOOP
//     }
// 
//     /*package*/
//     static boolean isSupported(final Class<?> type) {
//         return getSupportedClasses().contains(type);
//     }
// 
//     public static List<Class> getSupportedClasses() {
//         if (SUPPORTED_CLASSES.isEmpty()) {
//             final Class[] supportedArray;
//             try {
//                 supportedArray = ReflectionUtils.getClasses(PACKAGE_NAME);
//                 SUPPORTED_CLASSES.addAll(Arrays.asList(supportedArray));
//             } catch (ClassNotFoundException | IOException e) {
//                 e.printStackTrace();
//             }
//         }
//         return SUPPORTED_CLASSES;
//     }
// 
// 
// }
// 
// Path: src/main/java/com/michaelfotiadis/validator/annotated/processor/SearchPolicy.java
// public enum SearchPolicy {
//     SHALLOW,
//     DEEP
// }


import com.michaelfotiadis.validator.annotated.SupportedAnnotationContainer;
import com.michaelfotiadis.validator.annotated.processor.SearchPolicy;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
package com.michaelfotiadis.validator.annotated.parser;



/**
 *
 */
public class FieldParser {

    private static final Set<Class<?>> WRAPPER_TYPES = getWrapperTypes();
    private final Set<Object> visitedFields;

    public FieldParser() {
        this.visitedFields = new HashSet<>();
    }

    public static boolean isWrapperType(final Class<?> clazz) {
        return WRAPPER_TYPES.contains(clazz);
    }

    private static Set<Class<?>> getWrapperTypes() {
        final Set<Class<?>> primitiveWrappers = new HashSet<>();
        primitiveWrappers.add(Boolean.class);
        primitiveWrappers.add(Character.class);
        primitiveWrappers.add(Byte.class);
        primitiveWrappers.add(Short.class);
        primitiveWrappers.add(Integer.class);
        primitiveWrappers.add(Long.class);
        primitiveWrappers.add(Float.class);
        primitiveWrappers.add(String.class);
        primitiveWrappers.add(Number.class);
        primitiveWrappers.add(BigInteger.class);
        primitiveWrappers.add(BigDecimal.class);
        primitiveWrappers.add(String.class);
        primitiveWrappers.add(Double.class);
        primitiveWrappers.add(Void.class);
        return primitiveWrappers;
    }

    /**
     * Gets all declared {@link Field}s in a class
     *
     * @param obj {@link Object} to be processed
     * @return {@link List} of {@link Field} found
     */
// Path: src/main/java/com/michaelfotiadis/validator/annotated/SupportedAnnotationContainer.java
// public final class SupportedAnnotationContainer {
// 
//     private static final String PACKAGE_NAME = "com.michaelfotiadis.validator.annotated.annotations";
//     private static final List<Class> SUPPORTED_CLASSES = new ArrayList<>();
// 
//     private SupportedAnnotationContainer() {
//         // NOOP
//     }
// 
//     /*package*/
//     static boolean isSupported(final Class<?> type) {
//         return getSupportedClasses().contains(type);
//     }
// 
//     public static List<Class> getSupportedClasses() {
//         if (SUPPORTED_CLASSES.isEmpty()) {
//             final Class[] supportedArray;
//             try {
//                 supportedArray = ReflectionUtils.getClasses(PACKAGE_NAME);
//                 SUPPORTED_CLASSES.addAll(Arrays.asList(supportedArray));
//             } catch (ClassNotFoundException | IOException e) {
//                 e.printStackTrace();
//             }
//         }
//         return SUPPORTED_CLASSES;
//     }
// 
// 
// }
// 
// Path: src/main/java/com/michaelfotiadis/validator/annotated/processor/SearchPolicy.java
// public enum SearchPolicy {
//     SHALLOW,
//     DEEP
// }


// Path: src/main/java/com/michaelfotiadis/validator/annotated/parser/FieldParser.java
import com.michaelfotiadis.validator.annotated.SupportedAnnotationContainer;
import com.michaelfotiadis.validator.annotated.processor.SearchPolicy;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

package com.michaelfotiadis.validator.annotated.parser;



/**
 *
 */
public class FieldParser {

    private static final Set<Class<?>> WRAPPER_TYPES = getWrapperTypes();
    private final Set<Object> visitedFields;

    public FieldParser() {
        this.visitedFields = new HashSet<>();
    }

    public static boolean isWrapperType(final Class<?> clazz) {
        return WRAPPER_TYPES.contains(clazz);
    }

    private static Set<Class<?>> getWrapperTypes() {
        final Set<Class<?>> primitiveWrappers = new HashSet<>();
        primitiveWrappers.add(Boolean.class);
        primitiveWrappers.add(Character.class);
        primitiveWrappers.add(Byte.class);
        primitiveWrappers.add(Short.class);
        primitiveWrappers.add(Integer.class);
        primitiveWrappers.add(Long.class);
        primitiveWrappers.add(Float.class);
        primitiveWrappers.add(String.class);
        primitiveWrappers.add(Number.class);
        primitiveWrappers.add(BigInteger.class);
        primitiveWrappers.add(BigDecimal.class);
        primitiveWrappers.add(String.class);
        primitiveWrappers.add(Double.class);
        primitiveWrappers.add(Void.class);
        return primitiveWrappers;
    }

    /**
     * Gets all declared {@link Field}s in a class
     *
     * @param obj {@link Object} to be processed
     * @return {@link List} of {@link Field} found
     */
    public <T> List<Field> getDeclaredFields(final T obj, final SearchPolicy searchPolicy) {