/** 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);
  }