/**
   * Reset the commit order from the session's descriptors. This uses the constraint dependencies in
   * the descriptor's mappings, to decide which descriptors are dependent on which other
   * descriptors. Multiple computations of the commit order should produce the same ordering. This
   * is done to improve performance on unit of work writes through decreasing the stack size, and
   * acts as a deadlock avoidance mechanism.
   */
  public void initializeCommitOrder() {
    Vector descriptors = Helper.buildVectorFromMapElements(getSession().getDescriptors());

    // Must ensure uniqueness, some descriptor my be register twice for interfaces.
    descriptors = Helper.addAllUniqueToVector(new Vector(descriptors.size()), descriptors);
    Object[] descriptorsArray = new Object[descriptors.size()];
    for (int index = 0; index < descriptors.size(); index++) {
      descriptorsArray[index] = descriptors.elementAt(index);
    }
    Arrays.sort(descriptorsArray, new DescriptorCompare());
    descriptors = new Vector(descriptors.size());
    for (int index = 0; index < descriptorsArray.length; index++) {
      descriptors.addElement(descriptorsArray[index]);
    }

    CommitOrderCalculator calculator = new CommitOrderCalculator(getSession());
    calculator.addNodes(descriptors);
    calculator.calculateMappingDependencies();
    calculator.orderCommits();
    descriptors = calculator.getOrderedDescriptors();

    calculator = new CommitOrderCalculator(getSession());
    calculator.addNodes(descriptors);
    calculator.calculateSpecifiedDependencies();
    calculator.orderCommits();

    setCommitOrder(calculator.getOrderedClasses());
  }
 protected static boolean verifyFieldAndMapping(
     AbstractSession session,
     DatabaseField field,
     ClassDescriptor descriptor,
     DatabaseMapping mapping) {
   verifyField(session, field, descriptor);
   while (mapping.isAggregateObjectMapping()) {
     ClassDescriptor referenceDescriptor =
         ((AggregateObjectMapping) mapping).getReferenceDescriptor();
     mapping = referenceDescriptor.getObjectBuilder().getMappingForField(field);
     verifyFieldAndMapping(session, field, referenceDescriptor, mapping);
   }
   if (!mapping.isDirectToFieldMapping() && !mapping.isTransformationMapping()) {
     String mappingTypeName = Helper.getShortClassName(mapping);
     session
         .getIntegrityChecker()
         .handleError(
             DescriptorException.returningPolicyMappingNotSupported(
                 field.getName(), mappingTypeName, mapping));
     return false;
   } else {
     return true;
   }
 }
 /** INTERNAL: */
 public void validationAfterDescriptorInitialization(AbstractSession session) {
   Hashtable mapped = new Hashtable();
   for (int operation = INSERT; operation <= UPDATE; operation++) {
     if ((main[operation][MAPPED] != null) && !main[operation][MAPPED].isEmpty()) {
       Iterator it = main[operation][MAPPED].iterator();
       while (it.hasNext()) {
         DatabaseField field = (DatabaseField) it.next();
         mapped.put(field, field);
       }
     }
   }
   if (!mapped.isEmpty()) {
     for (Enumeration fields = getDescriptor().getFields().elements();
         fields.hasMoreElements(); ) {
       DatabaseField fieldInDescriptor = (DatabaseField) fields.nextElement();
       DatabaseField fieldInMain = (DatabaseField) mapped.get(fieldInDescriptor);
       if (fieldInMain != null) {
         if (fieldInMain.getType() == null) {
           if (getDescriptor().isReturnTypeRequiredForReturningPolicy()) {
             session
                 .getIntegrityChecker()
                 .handleError(
                     DescriptorException.returningPolicyMappedFieldTypeNotSet(
                         fieldInMain.getName(), getDescriptor()));
           }
         } else if (isThereATypeConflict(fieldInMain, fieldInDescriptor)) {
           session
               .getIntegrityChecker()
               .handleError(
                   DescriptorException.returningPolicyAndDescriptorFieldTypeConflict(
                       fieldInMain.getName(),
                       fieldInMain.getType().getName(),
                       fieldInDescriptor.getType().getName(),
                       getDescriptor()));
         }
       }
     }
   }
   if (!(session.getDatasourcePlatform() instanceof DatabasePlatform)) {
     // don't attempt further diagnostics on non-relational platforms
     return;
   }
   WriteObjectQuery[] query = {
     getDescriptor().getQueryManager().getInsertQuery(),
     getDescriptor().getQueryManager().getUpdateQuery()
   };
   String[] queryTypeName = {"InsertObjectQuery", "UpdateObjectQuery"};
   for (int operation = INSERT; operation <= UPDATE; operation++) {
     if ((main[operation][ALL] != null) && !main[operation][ALL].isEmpty()) {
       // this operation requires some fields to be returned
       if ((query[operation] == null) || (query[operation].getDatasourceCall() == null)) {
         if (!session.getPlatform().canBuildCallWithReturning()) {
           session
               .getIntegrityChecker()
               .handleError(
                   DescriptorException.noCustomQueryForReturningPolicy(
                       queryTypeName[operation],
                       Helper.getShortClassName(session.getPlatform()),
                       getDescriptor()));
         }
       } else if (query[operation].getDatasourceCall() instanceof StoredProcedureCall) {
         // SQLCall with custom SQL calculates its outputRowFields later (in prepare() method) -
         // that's why SQLCall can't be verified here.
         DatabaseCall customCall = (DatabaseCall) query[operation].getDatasourceCall();
         Enumeration outputRowFields = customCall.getOutputRowFields().elements();
         Collection notFoundInOutputRow = createCollection();
         notFoundInOutputRow.addAll(main[operation][ALL]);
         while (outputRowFields.hasMoreElements()) {
           notFoundInOutputRow.remove(outputRowFields.nextElement());
         }
         if (!notFoundInOutputRow.isEmpty()) {
           Iterator it = notFoundInOutputRow.iterator();
           while (it.hasNext()) {
             DatabaseField field = (DatabaseField) it.next();
             session
                 .getIntegrityChecker()
                 .handleError(
                     DescriptorException.customQueryAndReturningPolicyFieldConflict(
                         field.getName(), queryTypeName[operation], getDescriptor()));
           }
         }
       }
     }
   }
 }
 /** Print the in progress depth. */
 public String toString() {
   Object[] args = {Integer.valueOf(this.commitDepth)};
   return Helper.getShortClassName(getClass())
       + ToStringLocalization.buildMessage("commit_depth", args);
 }