Back to project page LitePal.
The source code is released under:
Apache License
If you think the Android project LitePal listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (C) Tony Green, Litepal Framework Open Source Project *//from w ww . ja va 2 s .c o m * 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 org.litepal.crud; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import org.litepal.LitePalBase; import org.litepal.crud.model.AssociationsInfo; import org.litepal.tablemanager.Connector; import org.litepal.util.BaseUtility; import org.litepal.util.DBUtility; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; /** * Deals analysis work when comes to two models are associated with Many2Many * associations. * * @author Tony Green * @since 1.1 */ public class Many2ManyAnalyzer extends AssociationsAnalyzer { /** * Analyzing the AssociationInfo. It will help baseObj assign the necessary * values automatically. If the two associated models have bidirectional * associations in class files but developer has only build unidirectional * associations in models, it will force to build the bidirectional * associations. Besides the * {@link DataSupport#addAssociatedModelForJoinTable(String, long)} will be called * here to put right values into tables. * * @param baseObj * The baseObj currently want to persist or update. * @param associationInfo * The associated info analyzed by * {@link LitePalBase#getRelatedInfo}. * @throws SecurityException * @throws IllegalArgumentException * @throws NoSuchMethodException * @throws IllegalAccessException * @throws InvocationTargetException */ void analyze(DataSupport baseObj, AssociationsInfo associationInfo) throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { Collection<DataSupport> associatedModels = getAssociatedModels(baseObj, associationInfo); declareAssociations(baseObj, associationInfo); if (associatedModels != null) { for (DataSupport associatedModel : associatedModels) { Collection<DataSupport> tempCollection = getReverseAssociatedModels( associatedModel, associationInfo); Collection<DataSupport> reverseAssociatedModels = checkAssociatedModelCollection( tempCollection, associationInfo.getAssociateSelfFromOtherModel()); addNewModelForAssociatedModel(reverseAssociatedModels, baseObj); setReverseAssociatedModels(associatedModel, associationInfo, reverseAssociatedModels); dealAssociatedModel(baseObj, associatedModel); } } } /** * This add an empty set for {@link DataSupport#associatedIdsM2M}. Might use * for updating intermediate join table. * * @param baseObj * The baseObj currently want to persist or update. * @param associationInfo * To get associated table name from. */ private void declareAssociations(DataSupport baseObj, AssociationsInfo associationInfo) { baseObj.addEmptyModelForJoinTable(getAssociatedTableName(associationInfo)); } /** * Force to build bidirectional associations for the associated model. If it * has already built, ignoring the rest process. * * @param associatedModelCollection * The associated models collection of the associated model. Add * self model into it if it doesn't contain self model yet. * @param baseObj * The baseObj currently want to persist or update. */ private void addNewModelForAssociatedModel(Collection<DataSupport> associatedModelCollection, DataSupport baseObj) { if (!associatedModelCollection.contains(baseObj)) { associatedModelCollection.add(baseObj); } } /** * First of all the associated model need to be saved already, or nothing * will be executed below. Then add the id of associated model into * {@link DataSupport#associatedIdsM2M} for inserting value into * intermediate join table after baseObj is saved. * * @param baseObj * The baseObj currently want to persist or update. * @param associatedModel * The associated model of baseObj. */ private void dealAssociatedModel(DataSupport baseObj, DataSupport associatedModel) { if (associatedModel.isSaved()) { baseObj.addAssociatedModelForJoinTable(associatedModel.getTableName(), associatedModel.getBaseObjId()); } } /** * Get the associated table name by {@link AssociationsInfo} after case * changed. * * @param associationInfo * To get the associated table name from. * @return The name of associated table with changed case. */ private String getAssociatedTableName(AssociationsInfo associationInfo) { return BaseUtility.changeCase(DBUtility.getTableNameByClassName(associationInfo .getAssociatedClassName())); } /** * Check if the associations between self model and associated model is * already saved into intermediate join table.<br> * Make sure baseObj and associatedModel are saved already, or the result * might be wrong. * * @param baseObj * The baseObj currently want to persist or update. * @param associatedModel * The associated model of baseObj. * @return If the associations between them is saved into intermediate join * table, return true. Otherwise return false. */ @SuppressWarnings("unused") @Deprecated private boolean isDataExists(DataSupport baseObj, DataSupport associatedModel) { boolean exists = false; SQLiteDatabase db = Connector.getDatabase(); Cursor cursor = null; try { cursor = db.query(getJoinTableName(baseObj, associatedModel), null, getSelection(baseObj, associatedModel), getSelectionArgs(baseObj, associatedModel), null, null, null); exists = cursor.getCount() > 0; } catch (Exception e) { e.printStackTrace(); return true; } finally { cursor.close(); } return exists; } /** * Build the selection for querying the data in table. Column names are the * table names with _id as suffix. * * @param baseObj * The baseObj currently want to persist or update. * @param associatedModel * The associated model of baseObj. * @return The selection clause for querying data. */ private String getSelection(DataSupport baseObj, DataSupport associatedModel) { StringBuilder where = new StringBuilder(); where.append(getForeignKeyColumnName(baseObj.getTableName())); where.append(" = ? and "); where.append(getForeignKeyColumnName(associatedModel.getTableName())); where.append(" = ?"); return where.toString(); } /** * Build the selection arguments to fill selection clause. * * @param baseObj * The baseObj currently want to persist or update. * @param associatedModel * The associated model of baseObj. * @return The selection arguments with the id of baseObj and * associatedModel to fill. */ private String[] getSelectionArgs(DataSupport baseObj, DataSupport associatedModel) { return new String[] { String.valueOf(baseObj.getBaseObjId()), String.valueOf(associatedModel.getBaseObjId()) }; } /** * Get the intermediate join table name for self model and associated model. * * @param baseObj * The baseObj currently want to persist or update. * @param associatedModel * The associated model of baseObj. * @return The intermediate join table name. */ private String getJoinTableName(DataSupport baseObj, DataSupport associatedModel) { return getIntermediateTableName(baseObj, associatedModel.getTableName()); } }