0001: /*
0002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com> and
0003: * JR Boyens <gnu-jrb[remove] at gmx dot net>
0004: * Distributed under the terms of either:
0005: * - the common development and distribution license (CDDL), v1.0; or
0006: * - the GNU Lesser General Public License, v2.1 or later
0007: * $Id: AbstractGenericQueryManager.java 3760 2007-05-14 13:37:33Z gbevin $
0008: */
0009: package com.uwyn.rife.database.querymanagers.generic;
0010:
0011: import com.uwyn.rife.database.*;
0012: import com.uwyn.rife.database.queries.*;
0013: import com.uwyn.rife.site.*;
0014: import java.util.*;
0015:
0016: import com.uwyn.rife.database.exceptions.DatabaseException;
0017: import com.uwyn.rife.database.exceptions.ExecutionErrorException;
0018: import com.uwyn.rife.database.exceptions.MissingManyToOneColumnException;
0019: import com.uwyn.rife.database.exceptions.MissingManyToOneTableException;
0020: import com.uwyn.rife.database.querymanagers.generic.exceptions.IncompatibleValidationTypeException;
0021: import com.uwyn.rife.database.querymanagers.generic.exceptions.UnsupportedManyToManyValueTypeException;
0022: import com.uwyn.rife.database.querymanagers.generic.instrument.LazyLoadAccessorsBytecodeTransformer;
0023: import com.uwyn.rife.tools.BeanUtils;
0024: import com.uwyn.rife.tools.ClassUtils;
0025: import com.uwyn.rife.tools.InnerClassException;
0026: import com.uwyn.rife.tools.StringUtils;
0027: import com.uwyn.rife.tools.TerracottaUtils;
0028: import com.uwyn.rife.tools.exceptions.BeanUtilsException;
0029: import java.lang.reflect.Field;
0030: import java.lang.reflect.Method;
0031:
0032: import static com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerRelationalUtils.ensureSupportedManyToManyPropertyValueType;
0033: import static com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerRelationalUtils.ensureSupportedManyToOneAssociationPropertyValueType;
0034: import static com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerRelationalUtils.generateManyToManyJoinColumnName;
0035: import static com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerRelationalUtils.generateManyToManyJoinTableName;
0036: import static com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerRelationalUtils.generateManyToOneJoinColumnName;
0037: import static com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerRelationalUtils.obtainManyToManyDeclarations;
0038: import static com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerRelationalUtils.obtainManyToOneAssociationDeclarations;
0039: import static com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerRelationalUtils.obtainManyToOneDeclarations;
0040: import static com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerRelationalUtils.processManyToOneJoinColumns;
0041: import static com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerRelationalUtils.restoreManyToOneProperty;
0042:
0043: public abstract class AbstractGenericQueryManager<BeanType> extends
0044: DbQueryManager implements GenericQueryManager<BeanType> {
0045: protected Class<BeanType> mBaseClass = null;
0046: protected String mPrimaryKey = null;
0047: protected Method mGetPrimaryKeyMethod = null;
0048: protected Method mSetPrimaryKeyMethod = null;
0049: protected boolean mSparseIdentifier = false;
0050:
0051: protected List<GenericQueryManagerListener> mListeners = null;
0052:
0053: public AbstractGenericQueryManager(Datasource datasource,
0054: Class<BeanType> beanClass, String primaryKey)
0055: throws DatabaseException {
0056: super (datasource);
0057:
0058: mBaseClass = beanClass;
0059: mPrimaryKey = primaryKey;
0060: try {
0061: String capitalized_primary_key = StringUtils
0062: .capitalize(mPrimaryKey);
0063: mGetPrimaryKeyMethod = mBaseClass.getMethod("get"
0064: + capitalized_primary_key, (Class[]) null);
0065: try {
0066: mSetPrimaryKeyMethod = mBaseClass.getMethod("set"
0067: + capitalized_primary_key,
0068: new Class[] { int.class });
0069: } catch (NoSuchMethodException e) {
0070: try {
0071: mSetPrimaryKeyMethod = mBaseClass.getMethod("set"
0072: + capitalized_primary_key,
0073: new Class[] { Integer.class });
0074: } catch (NoSuchMethodException e2) {
0075: throw e;
0076: }
0077: }
0078: } catch (Throwable e) {
0079: throw new DatabaseException(e);
0080: }
0081:
0082: Constrained constrained_bean = ConstrainedUtils
0083: .getConstrainedInstance(getBaseClass());
0084: if (constrained_bean != null) {
0085: ConstrainedProperty constrained_property = constrained_bean
0086: .getConstrainedProperty(primaryKey);
0087: if (constrained_property != null) {
0088: mSparseIdentifier = constrained_property.isSparse();
0089: }
0090: }
0091: }
0092:
0093: public Class getBaseClass() {
0094: return mBaseClass;
0095: }
0096:
0097: public String getIdentifierName() {
0098: return mPrimaryKey;
0099: }
0100:
0101: public int getIdentifierValue(BeanType bean)
0102: throws DatabaseException {
0103: try {
0104: Integer id = (Integer) mGetPrimaryKeyMethod.invoke(bean,
0105: (Object[]) null);
0106: if (null == id) {
0107: return -1;
0108: }
0109:
0110: return id.intValue();
0111: } catch (Throwable e) {
0112: throw new DatabaseException(e);
0113: }
0114: }
0115:
0116: public boolean isIdentifierSparse() {
0117: return mSparseIdentifier;
0118: }
0119:
0120: public void validate(Validated validated) {
0121: // perform validation
0122: if (validated != null && !(validated.getClass() == mBaseClass)) {
0123: throw new IncompatibleValidationTypeException(validated
0124: .getClass(), mBaseClass);
0125: }
0126:
0127: BeanType bean = (BeanType) validated;
0128:
0129: // handle before callback
0130: Callbacks callbacks = getCallbacks(bean);
0131: if (callbacks != null && !callbacks.beforeValidate(bean)) {
0132: return;
0133: }
0134: _validateWithoutCallbacks(validated);
0135:
0136: // handle after callback
0137: if (callbacks != null) {
0138: callbacks.afterValidate(bean);
0139: }
0140: }
0141:
0142: private static int getIdentifierValue(Object bean,
0143: String propertyName) throws DatabaseException {
0144: try {
0145: Integer id = (Integer) BeanUtils.getPropertyValue(bean,
0146: propertyName);
0147: if (null == id) {
0148: return -1;
0149: }
0150:
0151: return id.intValue();
0152: } catch (Throwable e) {
0153: throw new DatabaseException(e);
0154: }
0155: }
0156:
0157: protected void _validateWithoutCallbacks(final Validated validated) {
0158: if (null == validated) {
0159: return;
0160: }
0161:
0162: // handle constrained beans
0163: final Constrained constrained = ConstrainedUtils
0164: .makeConstrainedInstance(validated);
0165:
0166: if (constrained != null) {
0167: // check if the identifier exists or is still undefined (existing or
0168: // new entry)
0169: boolean identifier_exists = false;
0170: int identifier_value = getIdentifierValue((BeanType) validated);
0171: if (identifier_value >= 0) {
0172: identifier_exists = true;
0173: }
0174:
0175: // validate the many-to-one entities
0176: processManyToOneJoinColumns(this ,
0177: new ManyToOneJoinColumnProcessor() {
0178: public boolean processJoinColumn(
0179: String columnName, String propertyName,
0180: ManyToOneDeclaration declaration) {
0181: Object property_value = null;
0182: try {
0183: property_value = BeanUtils
0184: .getPropertyValue(constrained,
0185: propertyName);
0186: } catch (BeanUtilsException e) {
0187: throw new DatabaseException(e);
0188: }
0189:
0190: if (property_value != null) {
0191: int identifier_value = getIdentifierValue(
0192: property_value, declaration
0193: .getAssociationColumn());
0194: if (identifier_value >= 0) {
0195: if (!executeHasResultRows(declaration
0196: .getAssociationManager()
0197: .getRestoreQuery(
0198: identifier_value))) {
0199: validated
0200: .addValidationError(new ValidationError.INVALID(
0201: propertyName));
0202: }
0203: }
0204: }
0205:
0206: return true;
0207: }
0208: });
0209:
0210: Map<String, ManyToOneAssociationDeclaration> manytoone_association_declarations = null;
0211: Map<String, Object> manytoone_association_property_values = null;
0212: boolean obtained_manytoone_association_declarations = false;
0213:
0214: Map<String, ManyToManyDeclaration> manytomany_declarations = null;
0215: Map<String, Object> manytomany_property_values = null;
0216: boolean obtained_manytomany_declarations = false;
0217:
0218: // handle invididual properties
0219: for (ConstrainedProperty property : (Collection<ConstrainedProperty>) constrained
0220: .getConstrainedProperties()) {
0221: // handle the uniqueness of invididual properties
0222: if (property.isUnique()) {
0223: Object property_value = null;
0224: try {
0225: property_value = BeanUtils
0226: .getPropertyValue(constrained, property
0227: .getPropertyName());
0228: } catch (BeanUtilsException e) {
0229: throw new DatabaseException(e);
0230: }
0231:
0232: if (property_value != null) {
0233: CountQuery count_query = getCountQuery().where(
0234: property.getPropertyName(), "=",
0235: property_value);
0236: if (identifier_exists) {
0237: count_query.whereAnd(mPrimaryKey, "!=",
0238: identifier_value);
0239: }
0240:
0241: if (count(count_query) > 0) {
0242: validated
0243: .addValidationError(new ValidationError.UNICITY(
0244: property.getPropertyName()));
0245: }
0246: }
0247: }
0248:
0249: // handle the manyToOne constraint that contain the identifier values
0250: if (property.hasManyToOne()) {
0251: Object property_value = null;
0252: try {
0253: property_value = BeanUtils
0254: .getPropertyValue(constrained, property
0255: .getPropertyName());
0256: } catch (BeanUtilsException e) {
0257: throw new DatabaseException(e);
0258: }
0259:
0260: if (property_value != null
0261: && ClassUtils.isBasic(property_value
0262: .getClass())) {
0263: ConstrainedProperty.ManyToOne many_to_one = property
0264: .getManyToOne();
0265:
0266: if (null == many_to_one.getDerivedTable()) {
0267: throw new MissingManyToOneTableException(
0268: constrained.getClass(), property
0269: .getPropertyName());
0270: }
0271:
0272: if (null == many_to_one.getColumn()) {
0273: throw new MissingManyToOneColumnException(
0274: constrained.getClass(), property
0275: .getPropertyName());
0276: }
0277:
0278: if (!executeHasResultRows(new Select(
0279: getDatasource()).from(
0280: many_to_one.getDerivedTable()).where(
0281: many_to_one.getColumn(), "=",
0282: property_value))) {
0283: validated
0284: .addValidationError(new ValidationError.INVALID(
0285: property.getPropertyName()));
0286: }
0287: }
0288: }
0289:
0290: // handle the manyToOneAssociation constraint
0291: if (property.hasManyToOneAssociation()) {
0292: // make sure that the many to one association declarations have been obtained
0293: if (!obtained_manytoone_association_declarations) {
0294: manytoone_association_declarations = obtainManyToOneAssociationDeclarations(
0295: this , constrained);
0296:
0297: if (manytoone_association_declarations != null) {
0298: // get the property values of those that contain many-to-one association relationships
0299: String[] manytoone_association_property_names = new String[manytoone_association_declarations
0300: .size()];
0301: manytoone_association_declarations
0302: .keySet()
0303: .toArray(
0304: manytoone_association_property_names);
0305: try {
0306: manytoone_association_property_values = BeanUtils
0307: .getPropertyValues(
0308: constrained,
0309: manytoone_association_property_names,
0310: null, null);
0311: } catch (BeanUtilsException e) {
0312: throw new DatabaseException(e);
0313: }
0314: }
0315:
0316: obtained_manytoone_association_declarations = true;
0317: }
0318:
0319: ManyToOneAssociationDeclaration declaration = manytoone_association_declarations
0320: .get(property.getPropertyName());
0321: if (declaration != null) {
0322: Object value = manytoone_association_property_values
0323: .get(property.getPropertyName());
0324: Class type = declaration.getMainType();
0325: try {
0326: checkCollectionRelationshipValidity(
0327: validated, property, value, type);
0328: } catch (ClassCastException e) {
0329: throw new UnsupportedManyToManyValueTypeException(
0330: validated.getClass(), property
0331: .getName(), e);
0332: }
0333: }
0334: }
0335:
0336: // handle the manyToMany constraint
0337: if (property.hasManyToMany()
0338: || property.hasManyToManyAssociation()) {
0339: // make sure that the many to many declarations have been obtained
0340: if (!obtained_manytomany_declarations) {
0341: manytomany_declarations = obtainManyToManyDeclarations(
0342: this , constrained, true);
0343:
0344: if (manytomany_declarations != null) {
0345: // get the property values of those that contain many-to-many relationships
0346: String[] manytomany_property_names = new String[manytomany_declarations
0347: .size()];
0348: manytomany_declarations.keySet().toArray(
0349: manytomany_property_names);
0350: try {
0351: manytomany_property_values = BeanUtils
0352: .getPropertyValues(
0353: constrained,
0354: manytomany_property_names,
0355: null, null);
0356: } catch (BeanUtilsException e) {
0357: throw new DatabaseException(e);
0358: }
0359: }
0360:
0361: obtained_manytomany_declarations = true;
0362: }
0363:
0364: ManyToManyDeclaration declaration = manytomany_declarations
0365: .get(property.getPropertyName());
0366: if (declaration != null) {
0367: Object value = manytomany_property_values
0368: .get(property.getPropertyName());
0369: try {
0370: checkCollectionRelationshipValidity(
0371: validated, property, value,
0372: declaration.getAssociationType());
0373: } catch (ClassCastException e) {
0374: throw new UnsupportedManyToManyValueTypeException(
0375: validated.getClass(), property
0376: .getName(), e);
0377: }
0378: }
0379:
0380: }
0381: }
0382:
0383: // handle the bean-wide uniqueness
0384: ConstrainedBean constrained_bean = constrained
0385: .getConstrainedBean();
0386: if (constrained_bean != null
0387: && constrained_bean.hasUniques()) {
0388: for (String[] uniques : (List<String[]>) constrained_bean
0389: .getUniques()) {
0390: CountQuery count_query = getCountQuery();
0391: if (identifier_exists) {
0392: count_query.where(mPrimaryKey, "!=",
0393: identifier_value);
0394: }
0395:
0396: for (String unique : uniques) {
0397: Object property_value = null;
0398: try {
0399: property_value = BeanUtils
0400: .getPropertyValue(constrained,
0401: unique);
0402: } catch (BeanUtilsException e) {
0403: throw new DatabaseException(e);
0404: }
0405:
0406: if (null == property_value) {
0407: count_query = null;
0408: break;
0409: } else {
0410: count_query.where(unique, "=",
0411: property_value);
0412: }
0413: }
0414:
0415: if (count_query != null && count(count_query) > 0) {
0416: for (String unique : uniques) {
0417: validated
0418: .addValidationError(new ValidationError.UNICITY(
0419: unique));
0420: }
0421: }
0422: }
0423: }
0424: }
0425: }
0426:
0427: private void checkCollectionRelationshipValidity(
0428: final Validated validated,
0429: final ConstrainedProperty property,
0430: final Object propertyValue, final Class elementType)
0431: throws ClassCastException {
0432: if (elementType != null && propertyValue != null) {
0433: // cast the property value to a collection
0434: Collection value_collection = (Collection) propertyValue;
0435:
0436: // iterate over all the collection elements to obtain the identifier values
0437: Set<Integer> identifiers = new HashSet<Integer>();
0438: GenericQueryManager element_manager = createNewManager(elementType);
0439: for (Object entity : value_collection) {
0440: int identifier_value = element_manager
0441: .getIdentifierValue(entity);
0442: // only add the identifiers that have a value
0443: if (identifier_value != -1) {
0444: identifiers.add(identifier_value);
0445: }
0446: }
0447:
0448: // check if the many-to-one associations exist
0449: CountQuery count_query = element_manager.getCountQuery()
0450: .where(
0451: element_manager.getIdentifierName()
0452: + " IN ("
0453: + StringUtils
0454: .join(identifiers, ",")
0455: + ")");
0456: int count = element_manager.count(count_query);
0457: if (count != identifiers.size()) {
0458: validated
0459: .addValidationError(new ValidationError.INVALID(
0460: property.getPropertyName()));
0461: }
0462: }
0463: }
0464:
0465: protected Callbacks getCallbacks(BeanType bean) {
0466: if (null == bean)
0467: return null;
0468:
0469: Callbacks callbacks = null;
0470: if (bean instanceof CallbacksProvider) {
0471: callbacks = ((CallbacksProvider) bean).getCallbacks();
0472: } else if (bean instanceof Callbacks) {
0473: callbacks = (Callbacks) bean;
0474: }
0475: return callbacks;
0476: }
0477:
0478: protected int _update(final Update saveUpdate, final BeanType bean) {
0479: // handle before callback
0480: Callbacks callbacks = getCallbacks(bean);
0481: if (callbacks != null && !callbacks.beforeUpdate(bean)) {
0482: return -1;
0483: }
0484:
0485: // perform update
0486: int result = _updateWithoutCallbacks(saveUpdate, bean);
0487:
0488: // handle after callback
0489: if (callbacks != null) {
0490: callbacks.afterUpdate(bean, result != -1);
0491: }
0492:
0493: return result;
0494: }
0495:
0496: protected int _updateWithoutCallbacks(final Update saveUpdate,
0497: final BeanType bean) {
0498: assert saveUpdate != null;
0499:
0500: final int identifier_value = getIdentifierValue(bean);
0501: int result = (Integer) inTransaction(new DbTransactionUser() {
0502: public Integer useTransaction() throws InnerClassException {
0503: int result = identifier_value;
0504:
0505: storeManyToOne(bean);
0506:
0507: if (0 == executeUpdate(saveUpdate,
0508: new DbPreparedStatementHandler() {
0509: public void setParameters(
0510: final DbPreparedStatement statement) {
0511: statement.setBean(bean);
0512:
0513: setManyToOneJoinParameters(statement,
0514: bean);
0515: }
0516: })) {
0517: result = -1;
0518: } else {
0519: storeManyToOneAssociations(bean, identifier_value);
0520: storeManyToMany(bean, identifier_value);
0521: }
0522:
0523: return result;
0524: }
0525: });
0526:
0527: // handle listeners
0528: if (result != -1) {
0529: fireUpdated(bean);
0530: }
0531:
0532: return result;
0533: }
0534:
0535: protected int _insert(final SequenceValue nextId,
0536: final Insert save, final BeanType bean) {
0537: // handle before callback
0538: Callbacks callbacks = getCallbacks(bean);
0539: if (callbacks != null && !callbacks.beforeInsert(bean)) {
0540: return -1;
0541: }
0542:
0543: // perform insert
0544: int result = _insertWithoutCallbacks(nextId, save, bean);
0545:
0546: // handle after callback
0547: if (callbacks != null) {
0548: callbacks.afterInsert(bean, result != -1);
0549: }
0550:
0551: return result;
0552: }
0553:
0554: protected int _insertWithoutCallbacks(final SequenceValue nextId,
0555: final Insert save, final BeanType bean) {
0556: assert nextId != null;
0557: assert save != null;
0558:
0559: int value = -1;
0560:
0561: value = (Integer) inTransaction(new DbTransactionUser() {
0562: public Integer useTransaction() throws InnerClassException {
0563: storeManyToOne(bean);
0564:
0565: int result = getIdentifierValue(bean);
0566: if (!isIdentifierSparse()) {
0567: result = executeGetFirstInt(nextId);
0568: }
0569:
0570: final int primary_key_id = result;
0571: executeUpdate(save, new DbPreparedStatementHandler() {
0572: public void setParameters(
0573: final DbPreparedStatement statement) {
0574: statement.setBean(bean).setInt(mPrimaryKey,
0575: primary_key_id);
0576:
0577: setManyToOneJoinParameters(statement, bean);
0578: }
0579: });
0580:
0581: storeManyToOneAssociations(bean, primary_key_id);
0582: storeManyToMany(bean, primary_key_id);
0583:
0584: return result;
0585: }
0586: });
0587:
0588: try {
0589: mSetPrimaryKeyMethod.invoke(bean,
0590: new Object[] { new Integer(value) });
0591: } catch (Throwable e) {
0592: throw new DatabaseException(e);
0593: }
0594:
0595: // handle listeners
0596: if (value != -1) {
0597: fireInserted(bean);
0598: }
0599:
0600: return value;
0601: }
0602:
0603: protected void setManyToOneJoinParameters(
0604: final DbPreparedStatement statement, final BeanType bean) {
0605: final Constrained constrained = ConstrainedUtils
0606: .makeConstrainedInstance(bean);
0607:
0608: // handle many-to-one join column parameters
0609: processManyToOneJoinColumns(this ,
0610: new ManyToOneJoinColumnProcessor() {
0611: public boolean processJoinColumn(String columnName,
0612: String propertyName,
0613: ManyToOneDeclaration declaration) {
0614: try {
0615: Object join_column_property = BeanUtils
0616: .getPropertyValue(bean,
0617: propertyName);
0618: Object identifier_value = null;
0619: if (join_column_property != null) {
0620: identifier_value = BeanUtils
0621: .getPropertyValue(
0622: join_column_property,
0623: declaration
0624: .getAssociationColumn());
0625: }
0626: Class identifier_type = BeanUtils
0627: .getPropertyType(
0628: declaration
0629: .getAssociationType(),
0630: declaration
0631: .getAssociationColumn());
0632:
0633: int[] indices = statement
0634: .getParameterIndices(columnName);
0635: for (int index : indices) {
0636: getDatasource().getSqlConversion()
0637: .setTypedParameter(statement,
0638: index, identifier_type,
0639: columnName,
0640: identifier_value,
0641: constrained);
0642: }
0643: } catch (BeanUtilsException e) {
0644: throw new DatabaseException(e);
0645: }
0646:
0647: return true;
0648: }
0649: });
0650: }
0651:
0652: protected void storeManyToOne(final BeanType bean) {
0653: final Constrained constrained = ConstrainedUtils
0654: .makeConstrainedInstance(bean);
0655: final Map<String, ManyToOneDeclaration> declarations = obtainManyToOneDeclarations(
0656: this , constrained, null, null);
0657: if (declarations != null) {
0658: // get the property values of those that contain many-to-one relationships
0659: String[] property_names = new String[declarations.size()];
0660: declarations.keySet().toArray(property_names);
0661: final Map<String, Object> values;
0662: try {
0663: values = BeanUtils.getPropertyValues(bean,
0664: property_names, null, null);
0665: } catch (BeanUtilsException e) {
0666: throw new DatabaseException(e);
0667: }
0668:
0669: // iterate over all the many-to-one relationships that have associated classes and instance values
0670: for (Map.Entry<String, ManyToOneDeclaration> entry : declarations
0671: .entrySet()) {
0672: ManyToOneDeclaration declaration = entry.getValue();
0673: if (!declaration.isBasic()) {
0674: GenericQueryManager association_manager = declaration
0675: .getAssociationManager();
0676: String property_name = entry.getKey();
0677:
0678: // obtain the property value
0679: Object value = values.get(property_name);
0680: if (value != null) {
0681: int identifier_value = association_manager
0682: .getIdentifierValue(value);
0683: // insert the collection entries that have no identifier value
0684: if (identifier_value < 0) {
0685: identifier_value = association_manager
0686: .insert(value);
0687: }
0688: }
0689: }
0690: }
0691: }
0692: }
0693:
0694: protected void storeManyToOneAssociations(final BeanType bean,
0695: final int objectId) {
0696: final Constrained constrained = ConstrainedUtils
0697: .makeConstrainedInstance(bean);
0698: final Map<String, ManyToOneAssociationDeclaration> declarations = obtainManyToOneAssociationDeclarations(
0699: this , constrained);
0700: if (declarations != null) {
0701: // get the property values of those that contain many-to-one relationships
0702: String[] property_names = new String[declarations.size()];
0703: declarations.keySet().toArray(property_names);
0704: final Map<String, Object> values;
0705: try {
0706: values = BeanUtils.getPropertyValues(bean,
0707: property_names, null, null);
0708: } catch (BeanUtilsException e) {
0709: throw new DatabaseException(e);
0710: }
0711:
0712: // iterate over all the many-to-one relationships that have associated classes and instance values
0713: for (Map.Entry<String, ManyToOneAssociationDeclaration> entry : declarations
0714: .entrySet()) {
0715: ManyToOneAssociationDeclaration declaration = entry
0716: .getValue();
0717: GenericQueryManager main_manager = createNewManager(declaration
0718: .getMainType());
0719: String property_name = entry.getKey();
0720:
0721: // obtain the property value
0722: Object value = values.get(property_name);
0723:
0724: final String main_table = main_manager.getTable();
0725: final String main_identify_column = main_manager
0726: .getIdentifierName();
0727: final String main_join_column = generateManyToOneJoinColumnName(
0728: declaration.getMainProperty(), declaration
0729: .getMainDeclaration());
0730: Update clear_previous_mappings = new Update(
0731: getDatasource()).table(main_table).fieldCustom(
0732: main_join_column, "NULL");
0733: executeUpdate(clear_previous_mappings);
0734:
0735: if (value != null) {
0736: ensureSupportedManyToOneAssociationPropertyValueType(
0737: mBaseClass, property_name, value);
0738:
0739: Collection value_collection = (Collection) value;
0740:
0741: Update update_mapping = new Update(getDatasource())
0742: .table(main_table).fieldParameter(
0743: main_join_column).whereParameter(
0744: main_identify_column, "=");
0745: // store the collection entries
0746: for (Object many_to_one_entity : value_collection) {
0747: int identifier_value = main_manager
0748: .getIdentifierValue(many_to_one_entity);
0749: // insert the collection entries that have no identifier value
0750: if (identifier_value < 0) {
0751: identifier_value = main_manager
0752: .insert(many_to_one_entity);
0753: }
0754: // store the many-to-one mappings
0755: executeUpdate(
0756: update_mapping,
0757: new DbPreparedStatementHandler<Integer>(
0758: identifier_value) {
0759: public void setParameters(
0760: DbPreparedStatement statement) {
0761: statement.setInt(
0762: main_join_column,
0763: objectId).setInt(
0764: main_identify_column,
0765: getData());
0766: }
0767: });
0768: }
0769: }
0770: }
0771: }
0772: }
0773:
0774: protected void storeManyToMany(final BeanType bean,
0775: final int objectId) {
0776: final Constrained constrained = ConstrainedUtils
0777: .makeConstrainedInstance(bean);
0778: final Map<String, ManyToManyDeclaration> declarations = obtainManyToManyDeclarations(
0779: this , constrained, true);
0780: if (declarations != null) {
0781: // get the property values of those that contain many-to-many relationships
0782: String[] property_names = new String[declarations.size()];
0783: declarations.keySet().toArray(property_names);
0784: final Map<String, Object> values;
0785: try {
0786: values = BeanUtils.getPropertyValues(bean,
0787: property_names, null, null);
0788: } catch (BeanUtilsException e) {
0789: throw new DatabaseException(e);
0790: }
0791:
0792: // iterate over all the many to many relationships
0793: final String column1_name = generateManyToManyJoinColumnName(AbstractGenericQueryManager.this );
0794: for (Map.Entry<String, ManyToManyDeclaration> entry : declarations
0795: .entrySet()) {
0796: ManyToManyDeclaration declaration = entry.getValue();
0797: GenericQueryManager association_manager = createNewManager(declaration
0798: .getAssociationType());
0799: String join_table = generateManyToManyJoinTableName(
0800: declaration, AbstractGenericQueryManager.this ,
0801: association_manager);
0802: final String column2_name = generateManyToManyJoinColumnName(association_manager);
0803: String property_name = entry.getKey();
0804:
0805: // obtain the property value
0806: Object value = values.get(property_name);
0807:
0808: // create the delete statement to remove all the possible previous
0809: // mappings in the join table for this primary key ID
0810: Delete delete_previous_mappings = new Delete(
0811: getDatasource()).from(join_table).where(
0812: column1_name, "=", objectId);
0813: executeUpdate(delete_previous_mappings);
0814:
0815: if (value != null) {
0816: ensureSupportedManyToManyPropertyValueType(
0817: mBaseClass, property_name, value);
0818:
0819: Collection value_collection = (Collection) value;
0820:
0821: Insert insert_mapping = new Insert(getDatasource())
0822: .into(join_table).fieldParameter(
0823: column1_name).fieldParameter(
0824: column2_name);
0825: // store the collection entries
0826: for (Object many_to_many_entity : value_collection) {
0827: int identifier_value = association_manager
0828: .getIdentifierValue(many_to_many_entity);
0829: // insert the collection entries that have no identifier value
0830: if (identifier_value < 0) {
0831: identifier_value = association_manager
0832: .insert(many_to_many_entity);
0833: }
0834: // store the many-to_many mappings
0835: executeUpdate(
0836: insert_mapping,
0837: new DbPreparedStatementHandler<Integer>(
0838: identifier_value) {
0839: public void setParameters(
0840: DbPreparedStatement statement) {
0841: statement.setInt(column1_name,
0842: objectId)
0843: .setInt(column2_name,
0844: getData());
0845: }
0846: });
0847: }
0848: }
0849: }
0850: }
0851: }
0852:
0853: protected int _save(final SequenceValue nextId, final Insert save,
0854: final Update saveUpdate, final BeanType bean)
0855: throws DatabaseException {
0856: assert nextId != null;
0857: assert save != null;
0858: assert saveUpdate != null;
0859:
0860: int value = -1;
0861:
0862: // handle before callback
0863: final Callbacks callbacks = getCallbacks(bean);
0864: if (callbacks != null && !callbacks.beforeSave(bean)) {
0865: return -1;
0866: }
0867:
0868: // cancel indicator
0869: final boolean[] is_cancelled = new boolean[] { false };
0870:
0871: // perform save
0872: value = (Integer) inTransaction(new DbTransactionUser() {
0873: public Integer useTransaction() throws InnerClassException {
0874: int result = getIdentifierValue(bean);
0875: if (isIdentifierSparse()) {
0876: // handle before callback
0877: if (callbacks != null
0878: && !callbacks.beforeInsert(bean)) {
0879: is_cancelled[0] = true;
0880: return -1;
0881: }
0882:
0883: // try to perform the insert
0884: try {
0885: result = _insertWithoutCallbacks(nextId, save,
0886: bean);
0887: } catch (ExecutionErrorException e) {
0888: result = -1;
0889: }
0890:
0891: // handle after callback
0892: if (callbacks != null
0893: && !callbacks.afterInsert(bean,
0894: result != -1)) {
0895: is_cancelled[0] = true;
0896: return result;
0897: }
0898:
0899: // perform update if insert failed
0900: if (-1 == result) {
0901: // handle before callback
0902: if (callbacks != null
0903: && !callbacks.beforeUpdate(bean)) {
0904: is_cancelled[0] = true;
0905: return -1;
0906: }
0907:
0908: result = _updateWithoutCallbacks(saveUpdate,
0909: bean);
0910:
0911: // handle after callback
0912: if (callbacks != null
0913: && !callbacks.afterUpdate(bean,
0914: result != -1)) {
0915: is_cancelled[0] = true;
0916: return result;
0917: }
0918: }
0919: } else {
0920: // try to update
0921: if (result >= 0) {
0922: // handle before callback
0923: if (callbacks != null
0924: && !callbacks.beforeUpdate(bean)) {
0925: is_cancelled[0] = true;
0926: return -1;
0927: }
0928:
0929: result = _updateWithoutCallbacks(saveUpdate,
0930: bean);
0931:
0932: // handle after callback
0933: if (callbacks != null
0934: && !callbacks.afterUpdate(bean,
0935: result != -1)) {
0936: is_cancelled[0] = true;
0937: return result;
0938: }
0939: }
0940:
0941: // perform insert if update failed or wasn't appropriate
0942: if (-1 == result) {
0943: // handle before callback
0944: if (callbacks != null
0945: && !callbacks.beforeInsert(bean)) {
0946: is_cancelled[0] = true;
0947: return -1;
0948: }
0949:
0950: result = _insertWithoutCallbacks(nextId, save,
0951: bean);
0952:
0953: // handle after callback
0954: if (callbacks != null
0955: && !callbacks.afterInsert(bean,
0956: result != -1)) {
0957: is_cancelled[0] = true;
0958: return result;
0959: }
0960: }
0961: }
0962:
0963: return result;
0964: }
0965: });
0966:
0967: // handle after callback
0968: if (!is_cancelled[0] && callbacks != null) {
0969: callbacks.afterSave(bean, value != -1);
0970: }
0971:
0972: return value;
0973: }
0974:
0975: protected boolean _delete(Delete delete) throws DatabaseException {
0976: assert delete != null;
0977:
0978: boolean result = true;
0979:
0980: if (0 == executeUpdate(delete)) {
0981: result = false;
0982: }
0983:
0984: return result;
0985: }
0986:
0987: protected boolean _delete(final Delete delete, final int objectId)
0988: throws DatabaseException {
0989: assert delete != null;
0990:
0991: // handle before callback
0992: Callbacks callbacks = null;
0993: if (CallbacksProvider.class.isAssignableFrom(mBaseClass)) {
0994: try {
0995: callbacks = ((CallbacksProvider) mBaseClass
0996: .newInstance()).getCallbacks();
0997: } catch (IllegalAccessException e) {
0998: callbacks = null;
0999: } catch (InstantiationException e) {
1000: callbacks = null;
1001: }
1002: } else if (Callbacks.class.isAssignableFrom(mBaseClass)) {
1003: try {
1004: callbacks = (Callbacks) mBaseClass.newInstance();
1005: } catch (IllegalAccessException e) {
1006: callbacks = null;
1007: } catch (InstantiationException e) {
1008: callbacks = null;
1009: }
1010: }
1011: if (callbacks != null && !callbacks.beforeDelete(objectId)) {
1012: return false;
1013: }
1014:
1015: // perform delete
1016: Boolean result = inTransaction(new DbTransactionUser() {
1017: public Boolean useTransaction() throws InnerClassException {
1018: // remove all many-to-one mappings for this object ID
1019: deleteManyToOne(objectId);
1020:
1021: // remove all many-to-many mappings for this object ID
1022: deleteManyToMany(objectId);
1023:
1024: // perform the actual deletion of the object from the database
1025: if (0 == executeUpdate(delete,
1026: new DbPreparedStatementHandler() {
1027: public void setParameters(
1028: DbPreparedStatement statement) {
1029: statement.setInt(mPrimaryKey, objectId);
1030: }
1031: })) {
1032: return false;
1033: }
1034:
1035: return true;
1036: }
1037: });
1038:
1039: // handle listeners
1040: if (result) {
1041: fireDeleted(objectId);
1042: }
1043:
1044: // handle after callback
1045: if (callbacks != null) {
1046: callbacks.afterDelete(objectId, result);
1047: }
1048:
1049: return result;
1050: }
1051:
1052: protected void deleteManyToOne(final int objectId) {
1053: final Constrained constrained = ConstrainedUtils
1054: .getConstrainedInstance(getBaseClass());
1055: final Map<String, ManyToOneAssociationDeclaration> declarations = obtainManyToOneAssociationDeclarations(
1056: this , constrained);
1057: if (declarations != null) {
1058: // iterate over all the many to one assocation relationships
1059: for (Map.Entry<String, ManyToOneAssociationDeclaration> entry : declarations
1060: .entrySet()) {
1061: ManyToOneAssociationDeclaration declaration = entry
1062: .getValue();
1063: String column_name = generateManyToOneJoinColumnName(
1064: declaration.getMainProperty(), declaration
1065: .getMainDeclaration());
1066: GenericQueryManager main_manager = createNewManager(declaration
1067: .getMainType());
1068:
1069: // create an update statement that will set all the columns that
1070: // point to the deleted entity to NULL
1071: Update clear_references = new Update(getDatasource())
1072: .table(main_manager.getTable()).fieldCustom(
1073: column_name, "NULL").where(column_name,
1074: "=", objectId);
1075: executeUpdate(clear_references);
1076: }
1077: }
1078: }
1079:
1080: protected void deleteManyToMany(final int objectId) {
1081: final Constrained constrained = ConstrainedUtils
1082: .getConstrainedInstance(getBaseClass());
1083: final Map<String, ManyToManyDeclaration> declarations = obtainManyToManyDeclarations(
1084: this , constrained, true);
1085: if (declarations != null) {
1086: // iterate over all the many to many relationships
1087: final String column1_name = generateManyToManyJoinColumnName(AbstractGenericQueryManager.this );
1088: for (Map.Entry<String, ManyToManyDeclaration> entry : declarations
1089: .entrySet()) {
1090: ManyToManyDeclaration declaration = entry.getValue();
1091: GenericQueryManager association_manager = createNewManager(declaration
1092: .getAssociationType());
1093: String join_table = generateManyToManyJoinTableName(
1094: declaration, AbstractGenericQueryManager.this ,
1095: association_manager);
1096:
1097: // create the delete statement to remove all the possible previous
1098: // mappings in the join table for this primary key ID
1099: Delete delete_previous_mappings = new Delete(
1100: getDatasource()).from(join_table).where(
1101: column1_name, "=", objectId);
1102: executeUpdate(delete_previous_mappings);
1103: }
1104: }
1105: }
1106:
1107: protected BeanType _restore(Select restore, final int objectId)
1108: throws DatabaseException {
1109: assert restore != null;
1110:
1111: BeanType result = null;
1112:
1113: result = executeFetchFirstBean(restore, mBaseClass,
1114: new DbPreparedStatementHandler() {
1115: public void setParameters(
1116: DbPreparedStatement statement) {
1117: statement.setInt(mPrimaryKey, objectId);
1118: }
1119: });
1120:
1121: // handle listeners
1122: if (result != null) {
1123: restoreManyToOne(result);
1124: restoreManyToOneAssociations(result, objectId);
1125: restoreManyToMany(result, objectId);
1126:
1127: fireRestored(result);
1128: }
1129:
1130: // handle after callback
1131: Callbacks callbacks = getCallbacks(result);
1132: if (callbacks != null && !callbacks.afterRestore(result)) {
1133: return null;
1134: }
1135:
1136: return result;
1137: }
1138:
1139: protected BeanType _restoreFirst(Select restore)
1140: throws DatabaseException {
1141: assert restore != null;
1142:
1143: BeanType result = executeFetchFirstBean(restore, mBaseClass);
1144:
1145: // handle listeners
1146: if (result != null) {
1147: restoreManyToOne(result);
1148: int identifier_value = getIdentifierValue(result);
1149: restoreManyToOneAssociations(result, identifier_value);
1150: restoreManyToMany(result, identifier_value);
1151:
1152: fireRestored(result);
1153: }
1154:
1155: // handle after callback
1156: Callbacks callbacks = getCallbacks(result);
1157: if (callbacks != null && !callbacks.afterRestore(result)) {
1158: return null;
1159: }
1160:
1161: return result;
1162: }
1163:
1164: protected List<BeanType> _restore(Select restore)
1165: throws DatabaseException {
1166: assert restore != null;
1167:
1168: DbBeanFetcher<BeanType> bean_fetcher = new DbBeanFetcher<BeanType>(
1169: getDatasource(), mBaseClass, true) {
1170: public boolean gotBeanInstance(BeanType instance) {
1171: // handle listeners
1172: if (instance != null) {
1173: restoreManyToOne(instance);
1174: int identifier_value = getIdentifierValue(instance);
1175: restoreManyToOneAssociations(instance,
1176: identifier_value);
1177: restoreManyToMany(instance, identifier_value);
1178:
1179: fireRestored(instance);
1180: }
1181:
1182: // handle after callback
1183: Callbacks callbacks = getCallbacks(instance);
1184: return !(callbacks != null && !callbacks
1185: .afterRestore(instance));
1186: }
1187: };
1188:
1189: executeFetchAll(restore, bean_fetcher, null);
1190:
1191: return bean_fetcher.getCollectedInstances();
1192: }
1193:
1194: protected boolean _restore(Select restore,
1195: DbRowProcessor rowProcessor) throws DatabaseException {
1196: assert restore != null;
1197:
1198: return executeFetchAll(restore, rowProcessor);
1199: }
1200:
1201: protected void restoreManyToMany(final BeanType bean,
1202: final int objectId) {
1203: // handle many-to-many associations
1204: final Constrained constrained = ConstrainedUtils
1205: .makeConstrainedInstance(bean);
1206: final Map<String, ManyToManyDeclaration> declarations = obtainManyToManyDeclarations(
1207: this , constrained, true);
1208: if (declarations != null) {
1209: // iterate over all the many to many relationships
1210: final String column1_name = generateManyToManyJoinColumnName(AbstractGenericQueryManager.this );
1211: for (Map.Entry<String, ManyToManyDeclaration> entry : declarations
1212: .entrySet()) {
1213: ManyToManyDeclaration declaration = entry.getValue();
1214:
1215: // create the associations collection
1216: Object association_collection;
1217: if (Set.class == declaration.getCollectionType()) {
1218: association_collection = new ManyToManySet(
1219: AbstractGenericQueryManager.this ,
1220: column1_name, objectId, declaration);
1221: } else {
1222: association_collection = new ManyToManyList(
1223: AbstractGenericQueryManager.this ,
1224: column1_name, objectId, declaration);
1225: }
1226:
1227: // set the restore mappings as the property value
1228: try {
1229: BeanUtils.setPropertyValue(bean, entry.getKey(),
1230: association_collection);
1231: } catch (BeanUtilsException e) {
1232: throw new DatabaseException(e);
1233: }
1234: }
1235: }
1236: }
1237:
1238: protected void restoreManyToOne(final BeanType bean) {
1239: Field gqm_field = null;
1240: Field lazyloaded_field = null;
1241: try {
1242: gqm_field = bean.getClass().getDeclaredField(
1243: LazyLoadAccessorsBytecodeTransformer.GQM_VAR_NAME);
1244: lazyloaded_field = bean
1245: .getClass()
1246: .getDeclaredField(
1247: LazyLoadAccessorsBytecodeTransformer.LAZYLOADED_VAR_NAME);
1248: } catch (Exception e) {
1249: // if the synthetic fields don't exist in the class, just set them to null
1250: // since this means that bytecode enhancement hasn't been performed to provide
1251: // lazy-load functionalities
1252: gqm_field = null;
1253: lazyloaded_field = null;
1254: }
1255:
1256: // if the class has been enhanced for lazy loading capabilities, add a reference
1257: // to this GQM and create a new map for storing the already loaded property values
1258: if (gqm_field != null && lazyloaded_field != null) {
1259: gqm_field.setAccessible(true);
1260: lazyloaded_field.setAccessible(true);
1261: try {
1262: gqm_field.set(bean, this );
1263: if (TerracottaUtils.isTcPresent()) {
1264: lazyloaded_field.set(bean, new HashMap());
1265: } else {
1266: lazyloaded_field.set(bean, new WeakHashMap());
1267: }
1268: } catch (Exception e) {
1269: throw new DatabaseException(e);
1270: }
1271: }
1272: // otherwise eargerly load all many-to-one properties
1273: else {
1274: processManyToOneJoinColumns(this ,
1275: new ManyToOneJoinColumnProcessor() {
1276: public boolean processJoinColumn(
1277: String columnName, String propertyName,
1278: ManyToOneDeclaration declaration) {
1279: Object property_value = restoreManyToOneProperty(
1280: AbstractGenericQueryManager.this ,
1281: declaration.getAssociationManager(),
1282: columnName, declaration
1283: .getAssociationType());
1284:
1285: // set the many-to-one mapping as the property value
1286: try {
1287: BeanUtils.setPropertyValue(bean,
1288: propertyName, property_value);
1289: } catch (BeanUtilsException e) {
1290: throw new DatabaseException(e);
1291: }
1292:
1293: return true;
1294: }
1295: });
1296: }
1297: }
1298:
1299: protected void restoreManyToOneAssociations(final BeanType bean,
1300: final int objectId) {
1301: // handle many-to-one associations
1302: final Constrained constrained = ConstrainedUtils
1303: .makeConstrainedInstance(bean);
1304: final Map<String, ManyToOneAssociationDeclaration> declarations = obtainManyToOneAssociationDeclarations(
1305: this , constrained);
1306: if (declarations != null) {
1307: // iterate over all the many to one association relationships
1308: for (Map.Entry<String, ManyToOneAssociationDeclaration> entry : declarations
1309: .entrySet()) {
1310: ManyToOneAssociationDeclaration declaration = entry
1311: .getValue();
1312:
1313: // create the associations collection
1314: Object association_collection;
1315: if (Set.class == declaration.getCollectionType()) {
1316: association_collection = new ManyToOneAssociationSet(
1317: AbstractGenericQueryManager.this , objectId,
1318: declaration);
1319: } else {
1320: association_collection = new ManyToOneAssociationList(
1321: AbstractGenericQueryManager.this , objectId,
1322: declaration);
1323: }
1324:
1325: // set the restore mappings as the property value
1326: try {
1327: BeanUtils.setPropertyValue(bean, entry.getKey(),
1328: association_collection);
1329: } catch (BeanUtilsException e) {
1330: throw new DatabaseException(e);
1331: }
1332: }
1333: }
1334: }
1335:
1336: protected int _count(Select count) throws DatabaseException {
1337: return executeGetFirstInt(count);
1338: }
1339:
1340: protected void _install(final CreateSequence createSequence,
1341: final CreateTable createTable) throws DatabaseException {
1342: assert createSequence != null;
1343: assert createTable != null;
1344:
1345: inTransaction(new DbTransactionUserWithoutResult() {
1346: public void useTransactionWithoutResult()
1347: throws InnerClassException {
1348: if (!isIdentifierSparse()) {
1349: executeUpdate(createSequence);
1350: }
1351: executeUpdate(createTable);
1352:
1353: installManyToMany();
1354: }
1355: });
1356: fireInstalled();
1357: }
1358:
1359: protected void installManyToMany() {
1360: // create many-to-many join tables
1361: Constrained constrained = ConstrainedUtils
1362: .getConstrainedInstance(mBaseClass);
1363: Map<String, ManyToManyDeclaration> manytomany_declarations = obtainManyToManyDeclarations(
1364: this , constrained, false);
1365: if (manytomany_declarations != null) {
1366: String column1 = generateManyToManyJoinColumnName(AbstractGenericQueryManager.this );
1367: for (Map.Entry<String, ManyToManyDeclaration> entry : manytomany_declarations
1368: .entrySet()) {
1369: ManyToManyDeclaration declaration = entry.getValue();
1370: GenericQueryManager association_manager = createNewManager(declaration
1371: .getAssociationType());
1372: String table = generateManyToManyJoinTableName(
1373: declaration, AbstractGenericQueryManager.this ,
1374: association_manager);
1375: String column2 = generateManyToManyJoinColumnName(association_manager);
1376:
1377: // obtain the violation actions
1378: CreateTable.ViolationAction onupdate = null;
1379: CreateTable.ViolationAction ondelete = null;
1380: ConstrainedProperty property = constrained
1381: .getConstrainedProperty(entry.getKey());
1382: if (property != null && property.hasManyToMany()) {
1383: onupdate = property.getManyToMany().getOnUpdate();
1384: ondelete = property.getManyToMany().getOnDelete();
1385: }
1386:
1387: // build the table creation query
1388: CreateTable create_join_table = new CreateTable(
1389: getDatasource()).table(table).column(column1,
1390: int.class, CreateTable.NOTNULL).column(column2,
1391: int.class, CreateTable.NOTNULL).foreignKey(
1392: getTable(), column1, getIdentifierName(),
1393: onupdate, ondelete).foreignKey(
1394: association_manager.getTable(), column2,
1395: association_manager.getIdentifierName(),
1396: onupdate, ondelete);
1397: executeUpdate(create_join_table);
1398: }
1399: }
1400: }
1401:
1402: protected void _remove(final DropSequence dropSequence,
1403: final DropTable dropTable) throws DatabaseException {
1404: assert dropTable != null;
1405: assert dropSequence != null;
1406:
1407: inTransaction(new DbTransactionUserWithoutResult() {
1408: public void useTransactionWithoutResult()
1409: throws InnerClassException {
1410: removeManyToMany();
1411:
1412: // drop the table itself and optionally the sequence
1413: executeUpdate(dropTable);
1414: if (!isIdentifierSparse()) {
1415: executeUpdate(dropSequence);
1416: }
1417: }
1418: });
1419: fireRemoved();
1420: }
1421:
1422: protected void removeManyToMany() {
1423: // drop many-to-many join tables
1424: Constrained constrained = ConstrainedUtils
1425: .getConstrainedInstance(mBaseClass);
1426: Map<String, ManyToManyDeclaration> manytomany_declarations = obtainManyToManyDeclarations(
1427: this , constrained, false);
1428: if (manytomany_declarations != null) {
1429: for (Map.Entry<String, ManyToManyDeclaration> entry : manytomany_declarations
1430: .entrySet()) {
1431: ManyToManyDeclaration declaration = entry.getValue();
1432: GenericQueryManager association_manager = createNewManager(declaration
1433: .getAssociationType());
1434: String table = generateManyToManyJoinTableName(
1435: declaration, AbstractGenericQueryManager.this ,
1436: association_manager);
1437:
1438: // build the table removal query
1439: DropTable drop_join_table = new DropTable(
1440: getDatasource()).table(table);
1441: executeUpdate(drop_join_table);
1442: }
1443: }
1444: }
1445:
1446: public void addListener(GenericQueryManagerListener listener) {
1447: if (null == listener) {
1448: return;
1449: }
1450:
1451: if (null == mListeners) {
1452: mListeners = new ArrayList<GenericQueryManagerListener>();
1453: }
1454:
1455: mListeners.add(listener);
1456: }
1457:
1458: public void removeListeners() {
1459: if (null == mListeners) {
1460: return;
1461: }
1462:
1463: mListeners.clear();
1464: }
1465:
1466: public <OtherBeanType> GenericQueryManager<OtherBeanType> createNewManager(
1467: Class<OtherBeanType> beanClass) {
1468: return GenericQueryManagerFactory.getInstance(getDatasource(),
1469: beanClass);
1470: }
1471:
1472: protected void fireInstalled() {
1473: if (null == mListeners) {
1474: return;
1475: }
1476:
1477: for (GenericQueryManagerListener listener : mListeners) {
1478: listener.installed();
1479: }
1480: }
1481:
1482: protected void fireRemoved() {
1483: if (null == mListeners) {
1484: return;
1485: }
1486:
1487: for (GenericQueryManagerListener listener : mListeners) {
1488: listener.removed();
1489: }
1490: }
1491:
1492: protected void fireInserted(BeanType bean) {
1493: if (null == mListeners) {
1494: return;
1495: }
1496:
1497: for (GenericQueryManagerListener listener : mListeners) {
1498: listener.inserted(bean);
1499: }
1500: }
1501:
1502: protected void fireUpdated(BeanType bean) {
1503: if (null == mListeners) {
1504: return;
1505: }
1506:
1507: for (GenericQueryManagerListener listener : mListeners) {
1508: listener.updated(bean);
1509: }
1510: }
1511:
1512: protected void fireRestored(BeanType bean) {
1513: if (null == mListeners) {
1514: return;
1515: }
1516:
1517: for (GenericQueryManagerListener listener : mListeners) {
1518: listener.restored(bean);
1519: }
1520: }
1521:
1522: protected void fireDeleted(int objectId) {
1523: if (null == mListeners) {
1524: return;
1525: }
1526:
1527: for (GenericQueryManagerListener listener : mListeners) {
1528: listener.deleted(objectId);
1529: }
1530: }
1531: }
|