void mapObject(Object obj) {
    fieldMap.clear();
    initObject(obj, fieldMap);

    if (clazz.isAnnotationPresent(JQSchema.class)) {
      JQSchema schemaAnnotation = clazz.getAnnotation(JQSchema.class);
      // setup schema name mapping, if properly annotated
      if (!StringUtils.isNullOrEmpty(schemaAnnotation.name())) {
        schemaName = schemaAnnotation.name();
      }
    }

    if (clazz.isAnnotationPresent(JQTable.class)) {
      JQTable tableAnnotation = clazz.getAnnotation(JQTable.class);

      // setup table name mapping, if properly annotated
      if (!StringUtils.isNullOrEmpty(tableAnnotation.name())) {
        tableName = tableAnnotation.name();
      }

      // allow control over createTableIfRequired()
      createTableIfRequired = tableAnnotation.createIfRequired();

      // model version
      if (tableAnnotation.version() > 0) {
        tableVersion = tableAnnotation.version();
      }

      // setup the primary index, if properly annotated
      List<String> primaryKey = getColumns(tableAnnotation.primaryKey());
      if (primaryKey != null) {
        setPrimaryKey(primaryKey);
      }
    }

    if (clazz.isAnnotationPresent(JQIndex.class)) {
      JQIndex indexAnnotation = clazz.getAnnotation(JQIndex.class);

      // setup the indexes, if properly annotated
      addIndexes(IndexType.STANDARD, indexAnnotation.standard());
      addIndexes(IndexType.UNIQUE, indexAnnotation.unique());
      addIndexes(IndexType.HASH, indexAnnotation.hash());
      addIndexes(IndexType.UNIQUE_HASH, indexAnnotation.uniqueHash());
    }
  }
  void mapFields() {
    boolean byAnnotationsOnly = false;
    boolean inheritColumns = false;
    boolean strictTypeMapping = false;
    if (clazz.isAnnotationPresent(JQTable.class)) {
      JQTable tableAnnotation = clazz.getAnnotation(JQTable.class);
      byAnnotationsOnly = tableAnnotation.annotationsOnly();
      inheritColumns = tableAnnotation.inheritColumns();
      strictTypeMapping = tableAnnotation.strictTypeMapping();
    }

    List<Field> classFields = New.arrayList();
    classFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
    if (inheritColumns) {
      Class<?> superClass = clazz.getSuperclass();
      classFields.addAll(Arrays.asList(superClass.getDeclaredFields()));
    }

    for (Field f : classFields) {
      // default to field name
      String columnName = f.getName();
      boolean isAutoIncrement = false;
      boolean isPrimaryKey = false;
      int maxLength = 0;
      boolean trimString = false;
      boolean allowNull = true;
      String defaultValue = "";
      boolean hasAnnotation = f.isAnnotationPresent(JQColumn.class);
      if (hasAnnotation) {
        JQColumn col = f.getAnnotation(JQColumn.class);
        if (!StringUtils.isNullOrEmpty(col.name())) {
          columnName = col.name();
        }
        isAutoIncrement = col.autoIncrement();
        isPrimaryKey = col.primaryKey();
        maxLength = col.maxLength();
        trimString = col.trimString();
        allowNull = col.allowNull();
        defaultValue = col.defaultValue();
      }
      boolean isPublic = Modifier.isPublic(f.getModifiers());
      boolean reflectiveMatch = isPublic && !byAnnotationsOnly;
      if (reflectiveMatch || hasAnnotation) {
        FieldDefinition fieldDef = new FieldDefinition();
        fieldDef.field = f;
        fieldDef.columnName = columnName;
        fieldDef.isAutoIncrement = isAutoIncrement;
        fieldDef.isPrimaryKey = isPrimaryKey;
        fieldDef.maxLength = maxLength;
        fieldDef.trimString = trimString;
        fieldDef.allowNull = allowNull;
        fieldDef.defaultValue = defaultValue;
        fieldDef.dataType = ModelUtils.getDataType(fieldDef, strictTypeMapping);
        fields.add(fieldDef);
      }
    }
    List<String> primaryKey = New.arrayList();
    for (FieldDefinition fieldDef : fields) {
      if (fieldDef.isPrimaryKey) {
        primaryKey.add(fieldDef.columnName);
      }
    }
    if (primaryKey.size() > 0) {
      setPrimaryKey(primaryKey);
    }
  }