/** INTERNAL: */
  @Override
  public void process(AbstractSession session) {
    // Build the stored procedure call.
    StoredProcedureCall call = new StoredProcedureCall();

    // Process the stored procedure parameters.
    int index = 1;
    boolean callByIndex = callByIndex();
    boolean hasOutParameters = false;
    for (StoredProcedureParameterMetadata parameter : m_parameters) {
      parameter.processArgument(call, callByIndex, index);
      index++;

      // In JPA, if we have at least one out parameter we assume the
      // procedure does not return a result set.
      if (parameter.isOutParameter()) {
        hasOutParameters = true;
      }
    }

    // Process the procedure name.
    call.setProcedureName(m_procedureName);

    // Process the returns result set.
    call.setReturnsResultSet(returnsResultSet(hasOutParameters));

    // Process the multiple result sets.
    call.setHasMultipleResultSets(hasMultipleResultSets());

    // Create a JPA query to store internally on the session.
    JPAQuery query = new JPAQuery(getName(), call, processQueryHints(session));

    if (!m_resultClasses.isEmpty()) {
      // Process the multiple result classes.
      for (MetadataClass resultClass : m_resultClasses) {
        query.addResultClassNames(getJavaClassName(resultClass));
      }
    } else if (!m_resultSetMappings.isEmpty()) {
      // Process the multiple result set mapping.
      query.setResultSetMappings(m_resultSetMappings);
    } else {
      // Legacy support (EclipseLink @NamedStoreProcedureQuery).
      if (!getResultClass().isVoid()) {
        query.setResultClassName(getJavaClassName(getResultClass()));
      } else if (hasResultSetMapping(session)) {
        query.addResultSetMapping(getResultSetMapping());
      }
    }

    addJPAQuery(query, session);
  }
  public DatabaseCall getInsertCall() {
    DatabaseCall call = null;

    ObjectRelationalDatabaseField ordf = new ObjectRelationalDatabaseField("");
    ordf.setSqlType(Types.STRUCT);
    ordf.setSqlTypeName("PHONE_TYPE");
    ordf.setType(Phone.class);

    if (useCustomSQL) {
      String sqlString =
          "BEGIN SProc_Insert_PHolders(#ssn, #occupation, #sex, "
              + "#firstName, #birthDate, #lastName, #address, #childrenNames, #phones); END;";
      SQLCall sqlcall = new SQLCall(sqlString);
      sqlcall.setCustomSQLArgumentType("ssn", Long.class);
      sqlcall.setCustomSQLArgumentType("occupation", String.class);
      sqlcall.setCustomSQLArgumentType("sex", Character.class);
      sqlcall.setCustomSQLArgumentType("firstName", String.class);
      sqlcall.setCustomSQLArgumentType("birthDate", java.sql.Date.class);
      sqlcall.setCustomSQLArgumentType("lastName", String.class);
      sqlcall.setCustomSQLArgumentType("address", Types.STRUCT, "ADDRESS_TYPE");
      sqlcall.setCustomSQLArgumentType("childrenNames", Types.ARRAY, "NAMELIST_TYPE");
      sqlcall.setCustomSQLArgumentType("phones", Types.ARRAY, "PHONELIST_TYPE", ordf);
      call = sqlcall;
    } else {
      StoredProcedureCall spcall = new StoredProcedureCall();
      spcall.setProcedureName("SProc_Insert_PHolders");
      spcall.addUnamedArgument("ssn", Long.class);
      spcall.addUnamedArgument("occupation", String.class);
      spcall.addUnamedArgument("sex", Character.class);
      spcall.addUnamedArgument("firstName", String.class);
      spcall.addUnamedArgument("birthDate", java.sql.Date.class);
      spcall.addUnamedArgument("lastName", String.class);

      spcall.addUnamedArgument("address", Types.STRUCT, "ADDRESS_TYPE"); // Address.class
      spcall.addUnamedArgument("childrenNames", Types.ARRAY, "NAMELIST_TYPE");
      spcall.addUnamedArgument("phones", Types.ARRAY, "PHONELIST_TYPE", ordf);
      call = spcall;
    }
    return call;
  }
  public void test() {
    // stored procedure call
    StoredProcedureCall spCall = new StoredProcedureCall();
    spCall.setProcedureName("Read_All_Employees");
    spCall.useNamedCursorOutputAsResultSet("RESULT_CURSOR");

    // query
    DirectReadQuery query = new DirectReadQuery();
    query.setCall(spCall);
    query.useScrollableCursor();
    cursor = (ScrollableCursor) getSession().executeQuery(query);

    // If the driver returns a forward-only ResultSet initialized to afterLast there's nothing
    // ScrollableCursor can do with it.
    try {
      if ((cursor.getResultSet().isAfterLast())
          && (cursor.getResultSet().getType() == java.sql.ResultSet.TYPE_FORWARD_ONLY)) {
        throwWarning(
            "The ResultSet returned from the query is TYPE_FORWARD_ONLY and initialized to afterLast.");
      }
    } catch (java.sql.SQLException sqle) {
      throwWarning("Unexpected SQLException thrown while checking the ResultSet.");
    }

    // iterate the cursor
    try {
      while (cursor.hasNext()) {
        cursor.next();
      }
    } catch (org.eclipse.persistence.exceptions.DatabaseException dbe) {
      caughtException = dbe;
    } finally {
      if (cursor != null) {
        cursor.close();
      }
    }
  }