content: /*
   * Copyright (c) 2013. wyouflf (wyouflf@gmail.com)
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.lidroid.xutils.db.sqlite;
  
  import android.database.Cursor;
  import com.lidroid.xutils.DbUtils;
  import com.lidroid.xutils.db.table.*;
  import com.lidroid.xutils.util.LogUtils;
  
  import java.util.concurrent.ConcurrentHashMap;
  
  public class CursorUtils {
  
      @SuppressWarnings("unchecked")
      public static <T> T getEntity(final DbUtils db, final Cursor cursor, Class<T> entityType, long findCacheSequence) {
          if (db == null || cursor == null) return null;
  
          EntityTempCache.setSeq(findCacheSequence);
          try {
              Table table = Table.get(db, entityType);
              Id id = table.id;
              String idColumnName = id.getColumnName();
              int idIndex = id.getIndex();
              if (idIndex < 0) {
                  idIndex = cursor.getColumnIndex(idColumnName);
              }
              Object idValue = id.getColumnConverter().getFieldValue(cursor, idIndex);
              T entity = EntityTempCache.get(entityType, idValue);
              if (entity == null) {
                  entity = entityType.newInstance();
                  id.setValue2Entity(entity, cursor, idIndex);
                  EntityTempCache.put(entityType, idValue, entity);
              } else {
                  return entity;
              }
              int columnCount = cursor.getColumnCount();
              for (int i = 0; i < columnCount; i++) {
                  String columnName = cursor.getColumnName(i);
                  Column column = table.columnMap.get(columnName);
                  if (column != null) {
                      column.setValue2Entity(entity, cursor, i);
                  }
              }
  
              // init finder
              for (Finder finder : table.finderMap.values()) {
                  finder.setValue2Entity(entity, null, 0);
              }
              return entity;
          } catch (Throwable e) {
              LogUtils.e(e.getMessage(), e);
          }
  
          return null;
      }
  
      public static DbModel getDbModel(final Cursor cursor) {
          DbModel result = null;
          if (cursor != null) {
              result = new DbModel();
              int columnCount = cursor.getColumnCount();
              for (int i = 0; i < columnCount; i++) {
                  result.add(cursor.getColumnName(i), cursor.getString(i));
              }
          }
          return result;
      }
  
      public static class FindCacheSequence {
          private FindCacheSequence() {
          }
  
          private static long seq = 0;
          private static final String FOREIGN_LAZY_LOADER_CLASS_NAME = ForeignLazyLoader.class.getName();
          private static final String FINDER_LAZY_LOADER_CLASS_NAME = FinderLazyLoader.class.getName();
  
          public static long getSeq() {
              String findMethodCaller = Thread.currentThread().getStackTrace()[4].getClassName();
              if (!findMethodCaller.equals(FOREIGN_LAZY_LOADER_CLASS_NAME) && !findMethodCaller.equals(FINDER_LAZY_LOADER_CLASS_NAME)) {
                  ++seq;
              }
              return seq;
          }
      }
  
      private static class EntityTempCache {
          private EntityTempCache() {
          }
  
          private static final ConcurrentHashMap<String, Object> cache = new ConcurrentHashMap<String, Object>();
  
          private static long seq = 0;
  
          public static <T> void put(Class<T> entityType, Object idValue, Object entity) {
              cache.put(entityType.getName() + "#" + idValue, entity);
          }
  
          @SuppressWarnings("unchecked")
          public static <T> T get(Class<T> entityType, Object idValue) {
              return (T) cache.get(entityType.getName() + "#" + idValue);
          }
  
          public static void setSeq(long seq) {
              if (EntityTempCache.seq != seq) {
                  cache.clear();
                  EntityTempCache.seq = seq;
              }
          }
      }
  }
  