// 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;
    }

    private static <T> ImmutableMap<Integer, FixFieldMeta> scanFields(final Class<T> model,
                                                                      final MutableFixMetaDictionary dictionary,
                                                                      final Field... parentPath) {
        Map<Integer, FixFieldMeta> fixFields = Maps.newLinkedHashMap();

        for (Field f : model.getDeclaredFields()) {
            final Class<?> type = f.getType();
            final Field[] path = newPath(parentPath, f);

            for (Annotation annotation : f.getDeclaredAnnotations()) {
                if (FixField.class == annotation.annotationType()) {
                    FixField fixField = (FixField) annotation;
                    int tag = fixField.tag();
                    if (fixFields.containsKey(tag)) {
                        throw new FixException("There are more than one fields mapped with FIX tag [" + tag + "].");
                    }
                    fixFields.put(tag, fixFieldMeta(tag, fixField.header(), fixField.optional(), path));

                } else if (FixBlock.class == annotation.annotationType()) {
                    for (FixFieldMeta fixFieldMeta : scanClassAndAddToDictionary(type, dictionary).getFields()) {
                        Field[] fieldPath = ((FixDynamicFieldMeta) fixFieldMeta).getPath();
                        Field[] newFieldPath = Arrays.copyOf(path, path.length + fieldPath.length);
                        for (int i = path.length; i < newFieldPath.length; i++) {
                            newFieldPath[i] = fieldPath[i - path.length];
                        }
                        fixFields.put(fixFieldMeta.getTag(), new FixDynamicFieldMeta(
                                fixFieldMeta.getTag(),
                                fixFieldMeta.isHeader(),
// 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;

    }

    private static <T> ImmutableMap<Integer, FixFieldMeta> scanFields(final Class<T> model,
                                                                      final MutableFixMetaDictionary dictionary,
                                                                      final Field... parentPath) {
        Map<Integer, FixFieldMeta> fixFields = Maps.newLinkedHashMap();

        for (Field f : model.getDeclaredFields()) {
            final Class<?> type = f.getType();
            final Field[] path = newPath(parentPath, f);

            for (Annotation annotation : f.getDeclaredAnnotations()) {
                if (FixField.class == annotation.annotationType()) {
                    FixField fixField = (FixField) annotation;
                    int tag = fixField.tag();
                    if (fixFields.containsKey(tag)) {
                        throw new FixException("There are more than one fields mapped with FIX tag [" + tag + "].");
                    }
                    fixFields.put(tag, fixFieldMeta(tag, fixField.header(), fixField.optional(), path));

                } else if (FixBlock.class == annotation.annotationType()) {
                    for (FixFieldMeta fixFieldMeta : scanClassAndAddToDictionary(type, dictionary).getFields()) {
                        Field[] fieldPath = ((FixDynamicFieldMeta) fixFieldMeta).getPath();
                        Field[] newFieldPath = Arrays.copyOf(path, path.length + fieldPath.length);
                        for (int i = path.length; i < newFieldPath.length; i++) {
                            newFieldPath[i] = fieldPath[i - path.length];
                        }
                        fixFields.put(fixFieldMeta.getTag(), new FixDynamicFieldMeta(
                                fixFieldMeta.getTag(),
                                fixFieldMeta.isHeader(),
                                fixFieldMeta.isOptional(),