Android Open Source - ormdroid List Type Mapping






From Project

Back to project page ormdroid.

License

The source code is released under:

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUC...

If you think the Android project ormdroid listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.roscopeco.ormdroid;
//from  w w w. j a  va  2  s .  c om
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

public class ListTypeMapping implements TypeMapping {
  private static final String TAG = "ListTypeMapping";

  public Class<?> javaType() {
    return List.class;
  }

  // TODO make sure concreteType is not List, it should be the List's element, or change the argument to List<Class<?>>...
  public String sqlType(Class<?> concreteType) {
    // TODO basic typed lists not supported yet
    if(Number.class.isAssignableFrom(concreteType)) {
      return "BLOB"; // Raw packed numbers
    }
    else if(String.class.isAssignableFrom(concreteType)) {
      return "BLOB"; // Packed null-terminated strings
    }

    // Should never be reached, as Entity Lists must be inversed
    return "NONE";
  }

  public String encodeValue(SQLiteDatabase db, Object value) {
    Log.d(TAG, "encoding... " + value);

    @SuppressWarnings("unchecked")
    List<Entity> model = (List<Entity>)value;

    for(Entity entity : model) {
      if (entity.isTransient()) {
        if (db == null) {
          throw new IllegalArgumentException("Transient object doesn't make sense here");
        } else {
          TypeMapper.encodeValue(db, entity.save(db));
        }
      } else {
        TypeMapper.encodeValue(db, entity.getPrimaryKeyValue());
      }
    }

    return "<list>";
  }

  /*
   * TODO some thoughts for later...
   * 
   * * This is eager loading... Could lazy loading be implemented, perhaps with a custom List implementation?
   * * * Obviously random access would limit the usefulness of this, but might prevent loading the entire graph...
   * * * This would also push indeterminate load potentially onto the main thread at some later time...
   *
   */
  // TODO columnIndex == primaryKey for inverse fields... (+ many more dots...)
  public <T extends Entity> Object decodeValue(SQLiteDatabase db, Field field, Cursor c, int columnIndex, ArrayList<T> precursors) {
    Log.d(TAG, "decoding... " + field);

    Class<?> type = field.getType();

    if (List.class.isAssignableFrom(type)) {

      ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
      @SuppressWarnings("unchecked")
      Class<? extends Entity> expEntityType = (Class<? extends Entity>) parameterizedType.getActualTypeArguments()[0];
      // TODO parameterizedType.getActualTypeArguments().length should check to always == 1

      // TODO could use Query here? Maybe Query could have a primaryKey() method to select by prikey?
      Entity.EntityMapping map = Entity.getEntityMappingEnsureSchema(db, expEntityType);

      List<T> list;

      try {
        list = (List<T>) type.newInstance();
      }
      catch (IllegalAccessException e) {
        Log.e(TAG, "IllegalAccessExpression thrown");
        e.printStackTrace();
        return null;
      }
      catch (InstantiationException e) {
        Log.e(TAG, "InstantiationException thrown");
        e.printStackTrace();
        return null;
      }

      String inverseColumnName = field.getAnnotation(Column.class).inverse();

      // TODO non-inverse Lists (i.e. basic types) are not yet implemented
      if("".equals(inverseColumnName))
        return list;

      Log.d(TAG, "map.mTableName: " + map.mTableName);
      String sql = "SELECT * FROM " + map.mTableName + " WHERE " + inverseColumnName + "=" + columnIndex;
      Log.v(TAG, sql);
      Cursor valc = db.rawQuery(sql, null);

      // TODO if doing lazy loading, here could return custom list implementation, rather
      // than populating the list...
      if (valc.moveToFirst()) {
        do {
          list.add(map.load(db, valc, precursors));
        } while(valc.moveToNext());
      }

      valc.close();

      return list;

    } else {
      throw new IllegalArgumentException("ListTypeMapping can only be used with List subclasses");
    }
  }
}




Java Source Code List

com.roscopeco.ormdroid.Column.java
com.roscopeco.ormdroid.DateTypeMapping.java
com.roscopeco.ormdroid.EntityTypeMapping.java
com.roscopeco.ormdroid.Entity.java
com.roscopeco.ormdroid.ListTypeMapping.java
com.roscopeco.ormdroid.MappingList.java
com.roscopeco.ormdroid.NumericTypeMapping.java
com.roscopeco.ormdroid.ORMDroidApplication.java
com.roscopeco.ormdroid.ORMDroidException.java
com.roscopeco.ormdroid.Query.java
com.roscopeco.ormdroid.StringTypeMapping.java
com.roscopeco.ormdroid.Table.java
com.roscopeco.ormdroid.TypeMapper.java
com.roscopeco.ormdroid.TypeMappingException.java
com.roscopeco.ormdroid.TypeMapping.java