// Path: fixb/src/main/java/org/fixb/FixException.java
// public class FixException extends RuntimeException {
//     private static final long serialVersionUID = 1;
// 
//     /**
//      * @param tag the field tag that has not been found
//      * @param fixMessage the FIX message that does not contain the tag
//      * @return an instance of FixException for a field-not-found case.
//      */
//     public static FixException fieldNotFound(int tag, String fixMessage) {
//         return new FixException("Field [" + tag + "] was not found in message: " + fixMessage);
//     }
// 
//     /**
//      * @param message the exception message
//      * @param cause the exception cause
//      */
//     public FixException(final String message, final Throwable cause) {
//         super(message, cause);
//     }
// 
//     /**
//      * @param cause the exception cause
//      */
//     public FixException(final Throwable cause) {
//         super(cause.getMessage(), cause);
//     }
// 
//     /**
//      * @param message the exception message
//      */
//     public FixException(final String message) {
//         super(message);
//     }
// }
// 
// Path: fixb/src/main/java/org/fixb/FixConstants.java
// public static final int MSG_TYPE_TAG = 35;
// 
// Path: fixb/src/main/java/org/fixb/meta/FixFieldMeta.java
// public static FixFieldMeta fixFieldMeta(int tag, Object value, boolean header) {
//     return new FixConstantFieldMeta(tag, header, value);
// }
// 
// Path: fixb/src/main/java/org/fixb/meta/FixFieldMeta.java
// public static FixGroupMeta fixGroupMeta(int groupTag,
//                                         boolean header,
//                                         boolean optional,
//                                         int componentTag,
//                                         Class<?> componentType,
//                                         Field... path) {
//     return new FixGroupMeta(groupTag, header, optional, componentTag, componentType, path);
// }


import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.fixb.FixException;
import org.fixb.annotations.*;
import org.joda.time.Instant;
import org.joda.time.LocalDate;
import org.reflections.Reflections;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;
import static java.util.Arrays.asList;
import static org.fixb.FixConstants.MSG_TYPE_TAG;
import static org.fixb.meta.FixFieldMeta.fixFieldMeta;
import static org.fixb.meta.FixFieldMeta.fixGroupMeta;
    /**
     * Scans the given class for FIX mapping annotations.
     *
     * @param model the domain class to scan
     * @param <T>   the domain type to scan
     * @return a FixBlockMeta for the given type.
     * @throws FixException if the given class is not properly annotated.
     */
    public static <T> FixBlockMeta<T> scanClass(Class<T> model) {
        return scanClassAndAddToDictionary(model, new MutableFixMetaDictionary());
    }

    static <T> FixBlockMeta<T> scanClassAndAddToDictionary(Class<T> model, MutableFixMetaDictionary fixMetaDictionary) {
        if (fixMetaDictionary.containsMeta(model)) {
            return fixMetaDictionary.getComponentMeta(model);
        }

        final FixBlockMeta<T> result = scanClass(model, fixMetaDictionary);
        fixMetaDictionary.addMeta(result);
        return result;
    }

    static <T> FixBlockMeta<T> scanClass(Class<T> model, MutableFixMetaDictionary dictionary) {
        if (dictionary.containsMeta(model)) {
            return dictionary.getComponentMeta(model);
        }

        final FixBlockMeta<T> result;

        if (model.getConstructors().length == 0) {
// Path: fixb/src/main/java/org/fixb/FixException.java
// public class FixException extends RuntimeException {
//     private static final long serialVersionUID = 1;
// 
//     /**
//      * @param tag the field tag that has not been found
//      * @param fixMessage the FIX message that does not contain the tag
//      * @return an instance of FixException for a field-not-found case.
//      */
//     public static FixException fieldNotFound(int tag, String fixMessage) {
//         return new FixException("Field [" + tag + "] was not found in message: " + fixMessage);
//     }
// 
//     /**
//      * @param message the exception message
//      * @param cause the exception cause
//      */
//     public FixException(final String message, final Throwable cause) {
//         super(message, cause);
//     }
// 
//     /**
//      * @param cause the exception cause
//      */
//     public FixException(final Throwable cause) {
//         super(cause.getMessage(), cause);
//     }
// 
//     /**
//      * @param message the exception message
//      */
//     public FixException(final String message) {
//         super(message);
//     }
// }
// 
// Path: fixb/src/main/java/org/fixb/FixConstants.java
// public static final int MSG_TYPE_TAG = 35;
// 
// Path: fixb/src/main/java/org/fixb/meta/FixFieldMeta.java
// public static FixFieldMeta fixFieldMeta(int tag, Object value, boolean header) {
//     return new FixConstantFieldMeta(tag, header, value);
// }
// 
// Path: fixb/src/main/java/org/fixb/meta/FixFieldMeta.java
// public static FixGroupMeta fixGroupMeta(int groupTag,
//                                         boolean header,
//                                         boolean optional,
//                                         int componentTag,
//                                         Class<?> componentType,
//                                         Field... path) {
//     return new FixGroupMeta(groupTag, header, optional, componentTag, componentType, path);
// }


// Path: fixb/src/main/java/org/fixb/meta/FixMetaScanner.java
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.fixb.FixException;
import org.fixb.annotations.*;
import org.joda.time.Instant;
import org.joda.time.LocalDate;
import org.reflections.Reflections;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;
import static java.util.Arrays.asList;
import static org.fixb.FixConstants.MSG_TYPE_TAG;
import static org.fixb.meta.FixFieldMeta.fixFieldMeta;
import static org.fixb.meta.FixFieldMeta.fixGroupMeta;

    /**
     * Scans the given class for FIX mapping annotations.
     *
     * @param model the domain class to scan
     * @param <T>   the domain type to scan
     * @return a FixBlockMeta for the given type.
     * @throws FixException if the given class is not properly annotated.
     */
    public static <T> FixBlockMeta<T> scanClass(Class<T> model) {
        return scanClassAndAddToDictionary(model, new MutableFixMetaDictionary());
    }

    static <T> FixBlockMeta<T> scanClassAndAddToDictionary(Class<T> model, MutableFixMetaDictionary fixMetaDictionary) {
        if (fixMetaDictionary.containsMeta(model)) {
            return fixMetaDictionary.getComponentMeta(model);
        }

        final FixBlockMeta<T> result = scanClass(model, fixMetaDictionary);
        fixMetaDictionary.addMeta(result);
        return result;
    }

    static <T> FixBlockMeta<T> scanClass(Class<T> model, MutableFixMetaDictionary dictionary) {
        if (dictionary.containsMeta(model)) {
            return dictionary.getComponentMeta(model);
        }

        final FixBlockMeta<T> result;

        if (model.getConstructors().length == 0) {
            throw new FixException("Class [" + model.getName() + "] does not provide a public constructor.");