Search in sources :

Example 1 with GenericModel

use of org.litepal.tablemanager.model.GenericModel in project LitePal by LitePalFramework.

the class DataHandler method setGenericValueToModel.

/**
     * Get generic value from generic tables, then set the value into the baseObj.
     * @param baseObj
     *          The model to set into.
     * @param supportedGenericFields
     *          List of all supported generic fields.
     * @param genericModelMap
     *          Use HashMap to cache the query information at first loop. Then the rest loop can
     *          get query information directly to speed up.
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
protected void setGenericValueToModel(DataSupport baseObj, List<Field> supportedGenericFields, Map<Field, GenericModel> genericModelMap) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    for (Field field : supportedGenericFields) {
        String tableName, genericValueColumnName, genericValueIdColumnName, getMethodName;
        Cursor cursor = null;
        GenericModel genericModel = genericModelMap.get(field);
        if (genericModel == null) {
            tableName = DBUtility.getGenericTableName(baseObj.getClassName(), field.getName());
            genericValueColumnName = DBUtility.convertToValidColumnName(field.getName());
            genericValueIdColumnName = DBUtility.getGenericValueIdColumnName(baseObj.getClassName());
            getMethodName = genGetColumnMethod(field);
            GenericModel model = new GenericModel();
            model.setTableName(tableName);
            model.setValueColumnName(genericValueColumnName);
            model.setValueIdColumnName(genericValueIdColumnName);
            model.setGetMethodName(getMethodName);
            genericModelMap.put(field, model);
        } else {
            tableName = genericModel.getTableName();
            genericValueColumnName = genericModel.getValueColumnName();
            genericValueIdColumnName = genericModel.getValueIdColumnName();
            getMethodName = genericModel.getGetMethodName();
        }
        try {
            cursor = mDatabase.query(tableName, null, genericValueIdColumnName + " = ?", new String[] { String.valueOf(baseObj.getBaseObjId()) }, null, null, null);
            if (cursor.moveToFirst()) {
                do {
                    int columnIndex = cursor.getColumnIndex(BaseUtility.changeCase(genericValueColumnName));
                    if (columnIndex != -1) {
                        setToModelByReflection(baseObj, field, columnIndex, getMethodName, cursor);
                    }
                } while (cursor.moveToNext());
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
}
Also used : GenericModel(org.litepal.tablemanager.model.GenericModel) Field(java.lang.reflect.Field) Cursor(android.database.Cursor)

Example 2 with GenericModel

use of org.litepal.tablemanager.model.GenericModel in project LitePal by LitePalFramework.

the class DataHandler method setAssociatedModel.

/**
	 * Finds the associated models of baseObj, then set them into baseObj.
	 * 
	 * @param baseObj
	 *            The class of base object.
	 */
@SuppressWarnings({ "rawtypes", "unchecked" })
private void setAssociatedModel(DataSupport baseObj) {
    if (fkInOtherModel == null) {
        return;
    }
    for (AssociationsInfo info : fkInOtherModel) {
        Cursor cursor = null;
        String associatedClassName = info.getAssociatedClassName();
        boolean isM2M = info.getAssociationType() == Const.Model.MANY_TO_MANY;
        try {
            List<Field> supportedFields = getSupportedFields(associatedClassName);
            List<Field> supportedGenericFields = getSupportedGenericFields(associatedClassName);
            if (isM2M) {
                String tableName = baseObj.getTableName();
                String associatedTableName = DBUtility.getTableNameByClassName(associatedClassName);
                String intermediateTableName = DBUtility.getIntermediateTableName(tableName, associatedTableName);
                StringBuilder sql = new StringBuilder();
                sql.append("select * from ").append(associatedTableName).append(" a inner join ").append(intermediateTableName).append(" b on a.id = b.").append(associatedTableName + "_id").append(" where b.").append(tableName).append("_id = ?");
                cursor = DataSupport.findBySQL(BaseUtility.changeCase(sql.toString()), String.valueOf(baseObj.getBaseObjId()));
            } else {
                String foreignKeyColumn = getForeignKeyColumnName(DBUtility.getTableNameByClassName(info.getSelfClassName()));
                String associatedTableName = DBUtility.getTableNameByClassName(associatedClassName);
                cursor = mDatabase.query(BaseUtility.changeCase(associatedTableName), null, foreignKeyColumn + "=?", new String[] { String.valueOf(baseObj.getBaseObjId()) }, null, null, null, null);
            }
            if (cursor != null && cursor.moveToFirst()) {
                SparseArray<QueryInfoCache> queryInfoCacheSparseArray = new SparseArray<QueryInfoCache>();
                Map<Field, GenericModel> genericModelMap = new HashMap<Field, GenericModel>();
                do {
                    DataSupport modelInstance = (DataSupport) createInstanceFromClass(Class.forName(associatedClassName));
                    giveBaseObjIdValue(modelInstance, cursor.getLong(cursor.getColumnIndexOrThrow("id")));
                    setValueToModel(modelInstance, supportedFields, null, cursor, queryInfoCacheSparseArray);
                    setGenericValueToModel(modelInstance, supportedGenericFields, genericModelMap);
                    if (info.getAssociationType() == Const.Model.MANY_TO_ONE || isM2M) {
                        Field field = info.getAssociateOtherModelFromSelf();
                        Collection collection = (Collection) getFieldValue(baseObj, field);
                        if (collection == null) {
                            if (isList(field.getType())) {
                                collection = new ArrayList();
                            } else {
                                collection = new HashSet();
                            }
                            DynamicExecutor.setField(baseObj, field.getName(), collection, baseObj.getClass());
                        }
                        collection.add(modelInstance);
                    } else if (info.getAssociationType() == Const.Model.ONE_TO_ONE) {
                        setFieldValue(baseObj, info.getAssociateOtherModelFromSelf(), modelInstance);
                    }
                } while (cursor.moveToNext());
                queryInfoCacheSparseArray.clear();
                genericModelMap.clear();
            }
        } catch (Exception e) {
            throw new DataSupportException(e.getMessage(), e);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) DatabaseGenerateException(org.litepal.exceptions.DatabaseGenerateException) DataSupportException(org.litepal.exceptions.DataSupportException) InvocationTargetException(java.lang.reflect.InvocationTargetException) GenericModel(org.litepal.tablemanager.model.GenericModel) Field(java.lang.reflect.Field) SparseArray(android.util.SparseArray) DataSupportException(org.litepal.exceptions.DataSupportException) Collection(java.util.Collection) AssociationsInfo(org.litepal.crud.model.AssociationsInfo) HashSet(java.util.HashSet)

Example 3 with GenericModel

use of org.litepal.tablemanager.model.GenericModel in project LitePal by LitePalFramework.

the class DataHandler method query.

/**
	 * Query the table of the given model, returning a model list over the
	 * result set.
	 * 
	 * @param modelClass
	 *            The model to compile the query against.
	 * @param columns
	 *            A list of which columns to return. Passing null will return
	 *            all columns, which is discouraged to prevent reading data from
	 *            storage that isn't going to be used.
	 * @param selection
	 *            A filter declaring which rows to return, formatted as an SQL
	 *            WHERE clause (excluding the WHERE itself). Passing null will
	 *            return all rows for the given table.
	 * @param selectionArgs
	 *            You may include ?s in selection, which will be replaced by the
	 *            values from selectionArgs, in order that they appear in the
	 *            selection. The values will be bound as Strings.
	 * @param groupBy
	 *            A filter declaring how to group rows, formatted as an SQL
	 *            GROUP BY clause (excluding the GROUP BY itself). Passing null
	 *            will cause the rows to not be grouped.
	 * @param having
	 *            A filter declare which row groups to include in the cursor, if
	 *            row grouping is being used, formatted as an SQL HAVING clause
	 *            (excluding the HAVING itself). Passing null will cause all row
	 *            groups to be included, and is required when row grouping is
	 *            not being used.
	 * @param orderBy
	 *            How to order the rows, formatted as an SQL ORDER BY clause
	 *            (excluding the ORDER BY itself). Passing null will use the
	 *            default sort order, which may be unordered.
	 * @param limit
	 *            Limits the number of rows returned by the query, formatted as
	 *            LIMIT clause. Passing null denotes no LIMIT clause.
	 * @param foreignKeyAssociations
	 *            Associated classes which have foreign keys in the current
	 *            model's table.
	 * @return A model list. The list may be empty.
	 */
@SuppressWarnings("unchecked")
protected <T> List<T> query(Class<T> modelClass, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, List<AssociationsInfo> foreignKeyAssociations) {
    List<T> dataList = new ArrayList<T>();
    Cursor cursor = null;
    try {
        List<Field> supportedFields = getSupportedFields(modelClass.getName());
        List<Field> supportedGenericFields = getSupportedGenericFields(modelClass.getName());
        String[] customizedColumns = DBUtility.convertSelectClauseToValidNames(getCustomizedColumns(columns, supportedGenericFields, foreignKeyAssociations));
        String tableName = getTableName(modelClass);
        cursor = mDatabase.query(tableName, customizedColumns, selection, selectionArgs, groupBy, having, orderBy, limit);
        if (cursor.moveToFirst()) {
            SparseArray<QueryInfoCache> queryInfoCacheSparseArray = new SparseArray<QueryInfoCache>();
            Map<Field, GenericModel> genericModelMap = new HashMap<Field, GenericModel>();
            do {
                T modelInstance = (T) createInstanceFromClass(modelClass);
                giveBaseObjIdValue((DataSupport) modelInstance, cursor.getLong(cursor.getColumnIndexOrThrow("id")));
                setValueToModel(modelInstance, supportedFields, foreignKeyAssociations, cursor, queryInfoCacheSparseArray);
                setGenericValueToModel((DataSupport) modelInstance, supportedGenericFields, genericModelMap);
                if (foreignKeyAssociations != null) {
                    setAssociatedModel((DataSupport) modelInstance);
                }
                dataList.add(modelInstance);
            } while (cursor.moveToNext());
            queryInfoCacheSparseArray.clear();
            genericModelMap.clear();
        }
        return dataList;
    } catch (Exception e) {
        throw new DataSupportException(e.getMessage(), e);
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) DatabaseGenerateException(org.litepal.exceptions.DatabaseGenerateException) DataSupportException(org.litepal.exceptions.DataSupportException) InvocationTargetException(java.lang.reflect.InvocationTargetException) GenericModel(org.litepal.tablemanager.model.GenericModel) Field(java.lang.reflect.Field) SparseArray(android.util.SparseArray) DataSupportException(org.litepal.exceptions.DataSupportException)

Example 4 with GenericModel

use of org.litepal.tablemanager.model.GenericModel in project LitePal by LitePalFramework.

the class LitePalBase method manyToAnyConditions.

/**
	 * Deals with one to any association conditions. e.g. Song and Album. An
	 * album have many songs, and a song belongs to one album. So if there's an
	 * Album model defined in Song with private modifier, and in Album there's a
	 * List or Set with generic type of Song and declared as private modifier,
	 * they are one2many association. If there's no List or Set defined in
	 * Album, they will become one2one associations. If there's also a Song
	 * model defined in Album with private modifier, maybe the album just have
	 * one song, they are one2one association too.
	 * 
	 * When it's many2one association, it's easy to just simply add a foreign id
	 * column to the many side model's table. But when it comes to many2many
	 * association, it can not be done without intermediate join table in
	 * database. LitePal assumes that this join table's name is the
	 * concatenation of the two target table names in alphabetical order.
	 * 
	 * @param className
	 *            Source class name.
	 * @param field
	 *            A field of source class.
	 * @param action
	 *            Between {@link org.litepal.LitePalBase#GET_ASSOCIATIONS_ACTION} and
	 *            {@link org.litepal.LitePalBase#GET_ASSOCIATION_INFO_ACTION}
	 * 
	 * @throws ClassNotFoundException
	 */
private void manyToAnyConditions(String className, Field field, int action) throws ClassNotFoundException {
    if (isCollection(field.getType())) {
        String genericTypeName = getGenericTypeName(field);
        // this genericTypeName class.
        if (LitePalAttr.getInstance().getClassNames().contains(genericTypeName)) {
            Class<?> reverseDynamicClass = Class.forName(genericTypeName);
            Field[] reverseFields = reverseDynamicClass.getDeclaredFields();
            // Look up if there's a reverse association
            // definition in the reverse class.
            boolean reverseAssociations = false;
            for (int i = 0; i < reverseFields.length; i++) {
                Field reverseField = reverseFields[i];
                // Only map private fields
                if (!Modifier.isStatic(reverseField.getModifiers())) {
                    Class<?> reverseFieldTypeClass = reverseField.getType();
                    // associations.
                    if (className.equals(reverseFieldTypeClass.getName())) {
                        if (action == GET_ASSOCIATIONS_ACTION) {
                            addIntoAssociationModelCollection(className, genericTypeName, genericTypeName, Const.Model.MANY_TO_ONE);
                        } else if (action == GET_ASSOCIATION_INFO_ACTION) {
                            addIntoAssociationInfoCollection(className, genericTypeName, genericTypeName, field, reverseField, Const.Model.MANY_TO_ONE);
                        }
                        reverseAssociations = true;
                    } else // association.
                    if (isCollection(reverseFieldTypeClass)) {
                        String reverseGenericTypeName = getGenericTypeName(reverseField);
                        if (className.equals(reverseGenericTypeName)) {
                            if (action == GET_ASSOCIATIONS_ACTION) {
                                addIntoAssociationModelCollection(className, genericTypeName, null, Const.Model.MANY_TO_MANY);
                            } else if (action == GET_ASSOCIATION_INFO_ACTION) {
                                addIntoAssociationInfoCollection(className, genericTypeName, null, field, reverseField, Const.Model.MANY_TO_MANY);
                            }
                            reverseAssociations = true;
                        }
                    }
                }
            }
            // are many2one unidirectional associations.
            if (!reverseAssociations) {
                if (action == GET_ASSOCIATIONS_ACTION) {
                    addIntoAssociationModelCollection(className, genericTypeName, genericTypeName, Const.Model.MANY_TO_ONE);
                } else if (action == GET_ASSOCIATION_INFO_ACTION) {
                    addIntoAssociationInfoCollection(className, genericTypeName, genericTypeName, field, null, Const.Model.MANY_TO_ONE);
                }
            }
        } else if (BaseUtility.isGenericTypeSupported(genericTypeName) && action == GET_ASSOCIATIONS_ACTION) {
            Column annotation = field.getAnnotation(Column.class);
            if (annotation != null && annotation.ignore()) {
                return;
            }
            GenericModel genericModel = new GenericModel();
            genericModel.setTableName(DBUtility.getGenericTableName(className, field.getName()));
            genericModel.setValueColumnName(DBUtility.convertToValidColumnName(field.getName()));
            genericModel.setValueColumnType(getColumnType(genericTypeName));
            genericModel.setValueIdColumnName(DBUtility.getGenericValueIdColumnName(className));
            mGenericModels.add(genericModel);
        }
    }
}
Also used : GenericModel(org.litepal.tablemanager.model.GenericModel) Field(java.lang.reflect.Field) Column(org.litepal.annotation.Column)

Aggregations

Field (java.lang.reflect.Field)4 GenericModel (org.litepal.tablemanager.model.GenericModel)4 Cursor (android.database.Cursor)3 SparseArray (android.util.SparseArray)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 DataSupportException (org.litepal.exceptions.DataSupportException)2 DatabaseGenerateException (org.litepal.exceptions.DatabaseGenerateException)2 Collection (java.util.Collection)1 HashSet (java.util.HashSet)1 Column (org.litepal.annotation.Column)1 AssociationsInfo (org.litepal.crud.model.AssociationsInfo)1