protected Hashtable removeDuplicateAndValidateInfos(AbstractSession session) {
   Hashtable infoHashtable = new Hashtable();
   for (int i = 0; i < infos.size(); i++) {
     Info info1 = infos.get(i);
     info1 = (Info) info1.clone();
     DatabaseField descField = getDescriptor().buildField(info1.getField());
     if (info1.getField().getType() == null) {
       info1.setField(descField);
     } else {
       // keep the original type if specified
       info1.getField().setName(descField.getName());
       info1
           .getField()
           .setTableName(
               getDescriptor().getDefaultTable().getQualifiedNameDelimited(session.getPlatform()));
     }
     Info info2 = (Info) infoHashtable.get(info1.getField());
     if (info2 == null) {
       infoHashtable.put(info1.getField(), info1);
     } else {
       Info infoMerged = mergeInfos(info1, info2, session, getDescriptor());
       if (infoMerged != null) {
         // substitute info2 with infoMerged
         infoHashtable.put(infoMerged.getField(), infoMerged);
       } else {
         // couldn't merge info1 and info2 due to a conflict.
         // substitute info2 with info1
         infoHashtable.put(info1.getField(), info1);
       }
     }
   }
   return infoHashtable;
 }
  /** INTERNAL: Print SQL onto the stream, using the ExpressionPrinter for context */
  public void printSQL(ExpressionSQLPrinter printer) {
    if (isAttribute()) {
      printer.printField(getAliasedField());
    }

    // If the mapping is a direct collection then this falls into a gray area.
    // It must be treated as an attribute at this moment for it has a direct field.
    // However it is not an attribute in the sense that it also represents a foreign
    // reference and a mapping criteria has been added.
    // For bug 2900974 these are now handled as non-attributes during normalize but
    // as attributes when printing SQL.
    //
    if ((!isAttribute()) && (getMapping() != null) && getMapping().isDirectCollectionMapping()) {
      DirectCollectionMapping directCollectionMapping = (DirectCollectionMapping) getMapping();

      // The aliased table comes for free as it was a required part of the join criteria.
      TableExpression table =
          (TableExpression) getTable(directCollectionMapping.getReferenceTable());
      DatabaseTable aliasedTable = table.aliasForTable(table.getTable());
      DatabaseField aliasedField = (DatabaseField) directCollectionMapping.getDirectField().clone();
      aliasedField.setTable(aliasedTable);
      printer.printField(aliasedField);
    }

    if ((getMapping() != null) && getMapping().isNestedTableMapping()) {
      DatabaseTable tableAlias = aliasForTable(new NestedTable(this));
      printer.printString(tableAlias.getName());
    }
  }
 /** INTERNAL: */
 protected Vector<DatabaseField> getVectorOfFieldsToGenerate(int operation, DatabaseTable table) {
   if (this.main[operation][ALL] == null) {
     return null;
   }
   if (this.tableToFieldsForGenerationMap == null) {
     // the method is called for the first time
     tableToFieldsForGenerationMap = new HashMap[NUM_OPERATIONS];
   }
   if (this.tableToFieldsForGenerationMap[operation] == null) {
     // the method is called for the first time for this operation
     this.tableToFieldsForGenerationMap[operation] = new HashMap();
   }
   Vector<DatabaseField> fieldsForGeneration =
       this.tableToFieldsForGenerationMap[operation].get(table);
   if (fieldsForGeneration == null) {
     // the method is called for the first time for this operation and this table
     fieldsForGeneration = new NonSynchronizedVector();
     Iterator it = this.main[operation][ALL].iterator();
     while (it.hasNext()) {
       DatabaseField field = (DatabaseField) it.next();
       if (field.getTable().equals(table)) {
         fieldsForGeneration.add(field);
       }
     }
     this.tableToFieldsForGenerationMap[operation].put(table, fieldsForGeneration);
   }
   return fieldsForGeneration;
 }
 Info(DatabaseField field, boolean isInsert, boolean isInsertModeReturnOnly, boolean isUpdate) {
   this.field = field;
   if (field != null) {
     if (field.getType() != null) {
       setReferenceClass(field.getType());
     }
   }
   this.isInsert = isInsert;
   this.isInsertModeReturnOnly = isInsertModeReturnOnly;
   this.isUpdate = isUpdate;
 }
    @Override
    public int hashCode() {
      DatabaseField field = getField();
      Class type = field != null ? field.getType() : null;
      boolean isInsert = isInsert();
      boolean isInsertModeReturnOnly = isInsertModeReturnOnly();
      boolean isUpdate = isUpdate();

      int result = field != null ? field.hashCode() : 0;
      result = 31 * result + (type != null ? type.hashCode() : 0);
      result = 31 * result + (isInsert ? 1 : 0);
      result = 31 * result + (isInsertModeReturnOnly ? 1 : 0);
      result = 31 * result + (isUpdate ? 1 : 0);
      return result;
    }
  /** INTERNAL: Both ReturningPolicies should be initialized */
  public boolean hasEqualMains(ReturningPolicy policy) {
    Collection[][] mainToCompare = policy.main;
    if (main == mainToCompare) {
      return true;
    }
    for (int operation = INSERT; operation <= UPDATE; operation++) {
      for (int state = RETURN_ONLY; state < MAIN_SIZE; state++) {
        if ((main[operation][state] == null) && (mainToCompare[operation][state] != null)) {
          return false;
        }
        if ((main[operation][state] != null) && (mainToCompare[operation][state] == null)) {
          return false;
        }
        if (!main[operation][state].equals(mainToCompare[operation][state])) {
          return false;
        }
      }
    }

    // now compare types
    Hashtable allFields = new Hashtable();
    for (int operation = INSERT; operation <= UPDATE; operation++) {
      if (main[operation][ALL] != null) {
        Iterator it = main[operation][ALL].iterator();
        while (it.hasNext()) {
          DatabaseField field = (DatabaseField) it.next();
          allFields.put(field, field);
        }
      }
    }
    for (int operation = INSERT; operation <= UPDATE; operation++) {
      if (mainToCompare[operation][ALL] != null) {
        Iterator it = mainToCompare[operation][ALL].iterator();
        while (it.hasNext()) {
          DatabaseField fieldToCompare = (DatabaseField) it.next();
          DatabaseField field = (DatabaseField) allFields.get(fieldToCompare);
          if (!field.getType().equals(fieldToCompare.getType())) {
            return false;
          }
        }
      }
    }
    return true;
  }
 protected static boolean verifyField(
     AbstractSession session, DatabaseField field, ClassDescriptor descriptor) {
   boolean ok = true;
   if (field.equals(descriptor.getSequenceNumberField())) {
     ok = false;
     session
         .getIntegrityChecker()
         .handleError(
             DescriptorException.returningPolicyFieldNotSupported(field.getName(), descriptor));
   } else if (descriptor.hasInheritance()
       && field.equals(descriptor.getInheritancePolicy().getClassIndicatorField())) {
     ok = false;
     session
         .getIntegrityChecker()
         .handleError(
             DescriptorException.returningPolicyFieldNotSupported(field.getName(), descriptor));
   } else if (descriptor.usesOptimisticLocking()) {
     OptimisticLockingPolicy optimisticLockingPolicy = descriptor.getOptimisticLockingPolicy();
     if (optimisticLockingPolicy instanceof VersionLockingPolicy) {
       VersionLockingPolicy versionLockingPolicy = (VersionLockingPolicy) optimisticLockingPolicy;
       if (field.equals(versionLockingPolicy.getWriteLockField())) {
         ok = false;
         session
             .getIntegrityChecker()
             .handleError(
                 DescriptorException.returningPolicyFieldNotSupported(
                     field.getName(), descriptor));
       }
     }
   }
   return ok;
 }
 /** INTERNAL: */
 protected void fieldIsNotFromDescriptor(DatabaseField field) {
   if (field.getTable().equals(getDescriptor().getDefaultTable())) {
     if (this.fieldsNotFromDescriptor_DefaultTable == null) {
       this.fieldsNotFromDescriptor_DefaultTable = new HashMap();
     }
     this.fieldsNotFromDescriptor_DefaultTable.put(field, field);
   } else {
     if (this.fieldsNotFromDescriptor_OtherTables == null) {
       this.fieldsNotFromDescriptor_OtherTables = new HashMap();
     }
     this.fieldsNotFromDescriptor_OtherTables.put(field, field);
   }
 }
  /** INTERNAL: Alias the database field for our current environment */
  protected void initializeAliasedField() {
    DatabaseField tempField = (DatabaseField) getField().clone();
    DatabaseTable aliasedTable = getAliasedTable();

    //  Put in a special check here so that if the aliasing does nothing we don't cache the
    // result because it's invalid. This saves us from caching premature data if e.g. debugging
    // causes us to print too early"
    //	if (aliasedTable.equals(getField().getTable())) {
    //		return;
    //	} else {
    aliasedField = tempField;
    aliasedField.setTable(aliasedTable);
    //	}
  }
 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()));
           }
         }
       }
     }
   }
 }
  /** INTERNAL: */
  public void initialize(AbstractSession session) {
    clearInitialization();
    main = new Collection[NUM_OPERATIONS][MAIN_SIZE];

    // The order of descriptor initialization guarantees initialization of Parent before children.
    // main array is copied from Parent's ReturningPolicy
    if (getDescriptor().isChildDescriptor()) {
      ClassDescriptor parentDescriptor =
          getDescriptor().getInheritancePolicy().getParentDescriptor();
      if (parentDescriptor.hasReturningPolicy()) {
        copyMainFrom(parentDescriptor.getReturningPolicy());
      }
    }

    if (!infos.isEmpty()) {
      Hashtable infoHashtable = removeDuplicateAndValidateInfos(session);
      Hashtable infoHashtableUnmapped = (Hashtable) infoHashtable.clone();
      for (Enumeration fields = getDescriptor().getFields().elements();
          fields.hasMoreElements(); ) {
        DatabaseField field = (DatabaseField) fields.nextElement();
        Info info = (Info) infoHashtableUnmapped.get(field);
        if (info != null) {
          infoHashtableUnmapped.remove(field);
          if (verifyFieldAndMapping(session, field)) {
            if (info.getField().getType() == null) {
              addMappedFieldToMain(field, info);
            } else {
              addMappedFieldToMain(info.getField(), info);
              fieldIsNotFromDescriptor(info.getField());
            }
          }
        }
      }

      if (!infoHashtableUnmapped.isEmpty()) {
        Enumeration fields = infoHashtableUnmapped.keys();
        while (fields.hasMoreElements()) {
          DatabaseField field = (DatabaseField) fields.nextElement();
          Info info = (Info) infoHashtableUnmapped.get(field);
          if (verifyField(session, field, getDescriptor())) {
            if (field.getType() != null) {
              addUnmappedFieldToMain(field, info);
              fieldIsNotFromDescriptor(field);
              session.log(
                  SessionLog.FINEST,
                  SessionLog.QUERY,
                  "added_unmapped_field_to_returning_policy",
                  info.toString(),
                  getDescriptor().getJavaClassName());
            } else {
              if (getDescriptor().isReturnTypeRequiredForReturningPolicy()) {
                session
                    .getIntegrityChecker()
                    .handleError(
                        DescriptorException.returningPolicyUnmappedFieldTypeNotSet(
                            field.getName(), getDescriptor()));
              }
            }
          }
        }
      }
    }

    initializeIsUsedToSetPrimaryKey();
  }
 /** INTERNAL: */
 protected DatabaseField createField(String qualifiedName, Class type) {
   DatabaseField field = new DatabaseField(qualifiedName);
   field.setType(type);
   return field;
 }
 // used only on equal fields: field1.equals(field2)
 protected static boolean isThereATypeConflict(DatabaseField field1, DatabaseField field2) {
   return (field1.getType() != null)
       && (field2.getType() != null)
       && !field1.getType().equals(field2.getType());
 }
 public void setField(DatabaseField field) {
   this.field = field;
   if ((field.getType() == null) && (referenceClass != null)) {
     field.setType(referenceClass);
   }
 }