FileDocCategorySizeDatePackage
DatasourceCall.javaAPI DocGlassfish v2 API28741Tue May 22 16:54:20 BST 2007oracle.toplink.essentials.internal.databaseaccess

DatasourceCall

public abstract class DatasourceCall extends Object implements Call
INTERNAL: Purpose: Used as an abstraction of a datasource invocation.
author
James Sutherland
since
OracleAS TopLink 10g (10.0.3)

Fields Summary
protected DatabaseQuery
query
protected transient Vector
parameters
protected transient Vector
parameterTypes
public static final Integer
LITERAL
public static final Integer
MODIFY
public static final Integer
TRANSLATION
public static final Integer
CUSTOM_MODIFY
public static final Integer
OUT
public static final Integer
INOUT
public static final Integer
IN
public static final Integer
OUT_CURSOR
protected boolean
isPrepared
protected int
returnType
protected static final int
NO_RETURN
protected static final int
RETURN_ONE_ROW
protected static final int
RETURN_MANY_ROWS
protected static final int
RETURN_CURSOR
Constructors Summary
public DatasourceCall()


      
        this.isPrepared = false;
        this.returnType = RETURN_MANY_ROWS;
    
Methods Summary
public voidappendIn(java.io.Writer writer, DatabaseField field)
INTERNAL: All values are printed as ? to allow for parameter binding or translation during the execute of the call.

        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        getParameters().addElement(field);
        getParameterTypes().addElement(IN);
    
public voidappendInOut(java.io.Writer writer, DatabaseField inoutField)
INTERNAL: All values are printed as ? to allow for parameter binding or translation during the execute of the call.

        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        Object[] inOut = { inoutField, inoutField };
        getParameters().addElement(inOut);
        getParameterTypes().addElement(INOUT);
    
public voidappendLiteral(java.io.Writer writer, java.lang.Object literal)
INTERNAL: All values are printed as ? to allow for parameter binding or translation during the execute of the call.

        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        getParameters().addElement(literal);
        getParameterTypes().addElement(LITERAL);
    
public voidappendModify(java.io.Writer writer, DatabaseField modifyField)
INTERNAL: All values are printed as ? to allow for parameter binding or translation during the execute of the call.

        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        getParameters().addElement(modifyField);
        getParameterTypes().addElement(MODIFY);
    
public voidappendOut(java.io.Writer writer, DatabaseField outField)
INTERNAL: All values are printed as ? to allow for parameter binding or translation during the execute of the call.

        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        getParameters().addElement(outField);
        getParameterTypes().addElement(OUT);
    
public voidappendParameter(java.io.Writer writer, java.lang.Object parameter, oracle.toplink.essentials.internal.sessions.AbstractSession session)
Add the parameter. If using binding bind the parameter otherwise let the platform print it. The platform may also decide to bind the value.

        session.getDatasourcePlatform().appendParameter(this, writer, parameter);
    
public voidappendTranslation(java.io.Writer writer, DatabaseField modifyField)
INTERNAL: All values are printed as ? to allow for parameter binding or translation during the execute of the call.

        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        getParameters().addElement(modifyField);
        getParameterTypes().addElement(TRANSLATION);
    
public booleanareManyRowsReturned()
The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.

        return getReturnType() == RETURN_MANY_ROWS;
    
protected charargumentMarker()
INTERNAL: Return the character to use for the argument marker. ? is used in SQL, however other query languages such as XQuery need to use other markers.

        return '?";
    
public DatabaseQueryMechanismbuildNewQueryMechanism(DatabaseQuery query)
Return the appropriate mechanism, with the call added as necessary.

        return new DatasourceCallQueryMechanism(query, this);
    
public DatabaseQueryMechanismbuildQueryMechanism(DatabaseQuery query, DatabaseQueryMechanism mechanism)
Return the appropriate mechanism, with the call added as necessary.

        if (mechanism.isCallQueryMechanism() && (mechanism instanceof DatasourceCallQueryMechanism)) {
            // Must also add the call singleton...
            DatasourceCallQueryMechanism callMechanism = ((DatasourceCallQueryMechanism)mechanism);
            if (!callMechanism.hasMultipleCalls()) {
                callMechanism.addCall(callMechanism.getCall());
                callMechanism.setCall(null);
            }
            callMechanism.addCall(this);
            return mechanism;
        } else {
            return buildNewQueryMechanism(query);
        }
    
public java.lang.Objectclone()

        try {
            return super.clone();
        } catch (CloneNotSupportedException exception) {
            ;//Do nothing
        }

        return null;
    
protected DatabaseFieldcreateField(java.lang.String fieldName)
INTERNAL: Create a new Database Field This method can be overridden by subclasses to return other field types

        return new DatabaseField(fieldName);
    
protected java.lang.ObjectcreateInOutParameter(java.lang.Object inValue, java.lang.Object outParameter, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Returns INOUT parameter. Called by getValueForInOutParameter method. Descendents may override this method.

        Object[] inOut = { inValue, outParameter };
        return inOut;
    
public abstract java.lang.StringgetLogString(Accessor accessor)
Return the SQL string for logging purposes.

public java.util.VectorgetParameterTypes()
The parameter types determine if the parameter is a modify, translation or litteral type.

        if (parameterTypes == null) {
            parameterTypes = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance();
        }
        return parameterTypes;
    
public java.util.VectorgetParameters()
The parameters are the values in order of occurance in the SQL statement. This is lazy initialized to conserv space on calls that have no parameters.

        if (parameters == null) {
            parameters = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance();
        }
        return parameters;
    
public DatabaseQuerygetQuery()
Back reference to query, unfortunately required for events.

        return query;
    
public java.lang.StringgetQueryString()
Return the query string of the call. This must be overwritten by subclasses that support query language translation (SQLCall, XQueryCall).

        return "";
    
public intgetReturnType()
The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.

        return returnType;
    
protected java.lang.ObjectgetValueForInOutParameter(java.lang.Object parameter, oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow, oracle.toplink.essentials.internal.sessions.AbstractRecord modifyRow, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Returns value for INOUT parameter. Called by translate and translateSQLString methods.

        // parameter ts an array of two Objects: inParameter and outParameter
        Object inParameter = ((Object[])parameter)[0];
        Object inValue = getValueForInParameter(inParameter, translationRow, modifyRow, session, true);
        Object outParameter = ((Object[])parameter)[1];
        return createInOutParameter(inValue, outParameter, session);
    
protected java.lang.ObjectgetValueForInParameter(java.lang.Object parameter, oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow, oracle.toplink.essentials.internal.sessions.AbstractRecord modifyRow, oracle.toplink.essentials.internal.sessions.AbstractSession session, boolean shouldBind)
INTERNAL: Returns value for IN parameter. Called by translate and translateSQLString methods. In case shouldBind==true tries to return a DatabaseField with type instead of null, returns null only in case no DatabaseField with type was found.

        Object value = parameter;

        // Parameter expressions are used for nesting and correct mapping conversion of the value.
        if (parameter instanceof ParameterExpression) {
            value = ((ParameterExpression)parameter).getValue(translationRow, session);
        } else if (parameter instanceof DatabaseField) {
            DatabaseField field = (DatabaseField)parameter;
            value = translationRow.get(field);
            // Must check for the modify row as well for custom SQL compatibility as only one # is required.
            if (modifyRow != null) {
                if (value == null) {
                    value = modifyRow.get(field);
                }
                if (value != null) {
                    DatabaseField modifyField = modifyRow.getField(field);
                    if (modifyField != null) {
                        if (session.getDatasourcePlatform().shouldUseCustomModifyForCall(modifyField)) {
                            value = session.getDatasourcePlatform().getCustomModifyValueForCall(this, value, modifyField, shouldBind);
                        }
                    }
                }
            }
            if ((value == null) && shouldBind) {
                if (field.getType() != null) {
                    value = field;
                } else if (modifyRow != null) {
                    DatabaseField modifyField = modifyRow.getField(field);
                    if ((modifyField != null) && (modifyField.getType() != null)) {
                        value = modifyField;
                    }
                }
                if (value == null) {
                    DatabaseField translationField = translationRow.getField(field);
                    if (translationField == null){
                        throw QueryException.namedArgumentNotFoundInQueryParameters(field.getName());
                    }
                    if (translationField.getType() != null) {
                        value = translationField;
                    }
                }
            }
        }
        return value;
    
public booleanhasParameters()
The parameters are the values in order of occurance in call. This is lazy initialized to conserv space on calls that have no parameters.

        return (parameters != null) && (!getParameters().isEmpty());
    
public booleanisCursorReturned()
The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.

        return getReturnType() == RETURN_CURSOR;
    
public booleanisEISInteraction()

        return false;
    
public booleanisEJBQLCall()

        return false;
    
public booleanisFinished()
Return whether all the results of the call have been returned.

        return !isCursorReturned();
    
public booleanisNothingReturned()
The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.

        return getReturnType() == NO_RETURN;
    
public booleanisOneRowReturned()
The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.

        return getReturnType() == RETURN_ONE_ROW;
    
public booleanisOutputParameterType(java.lang.Integer parameterType)

        return (parameterType == OUT) || (parameterType == INOUT) || (parameterType == OUT_CURSOR);
    
protected booleanisPrepared()
Bound calls can have the SQL pre generated.

        return isPrepared;
    
public booleanisQueryStringCall()

        return false;
    
public booleanisSQLCall()

        return false;
    
public booleanisStoredFunctionCall()

        return false;
    
public booleanisStoredProcedureCall()

        return false;
    
public voidprepare(oracle.toplink.essentials.internal.sessions.AbstractSession session)
Allow pre-printing of the query/SQL string for fully bound calls, to save from reprinting.

        setIsPrepared(true);
    
public voidreturnCursor()
Cursor return is used for cursored streams.

        setReturnType(RETURN_CURSOR);
    
public voidreturnManyRows()
Many rows are returned for read-all queries.

        setReturnType(RETURN_MANY_ROWS);
    
public voidreturnNothing()
No return is used for modify calls like insert / update / delete.

        setReturnType(NO_RETURN);
    
public voidreturnOneRow()
One row is returned for read-object queries.

        setReturnType(RETURN_ONE_ROW);
    
protected voidsetIsPrepared(boolean isPrepared)
Bound calls can have the SQL pre generated.

        this.isPrepared = isPrepared;
    
public voidsetParameterTypes(java.util.Vector parameterTypes)
The parameter types determine if the parameter is a modify, translation or litteral type.

        this.parameterTypes = parameterTypes;
    
public voidsetParameters(java.util.Vector parameters)
The parameters are the values in order of occurance in the SQL statement.

        this.parameters = parameters;
    
public voidsetQuery(DatabaseQuery query)
Back reference to query, unfortunately required for events.

        this.query = query;
    
public voidsetQueryString(java.lang.String queryString)
Set the query string of the call. This must be overwritten by subclasses that support query language translation (SQLCall, XQueryCall).

        // Nothing by default.
    
public voidsetReturnType(int returnType)
The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.

        this.returnType = returnType;
    
public voidtranslate(oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow, oracle.toplink.essentials.internal.sessions.AbstractRecord modifyRow, oracle.toplink.essentials.internal.sessions.AbstractSession session)
Allow the call to translate from the translation for predefined calls.

        //do nothing by default.
    
public voidtranslateCustomQuery()
INTERNAL: Parse the query string for # markers for custom query based on a query language. This is used by SQLCall and XQuery call, but can be reused by other query languages.

        if (getQueryString().indexOf("#") == -1) {
            if (this.getQuery().shouldBindAllParameters() && getQueryString().indexOf("?") == -1){
                return;
            }
            translatePureSQLCustomQuery();
            return;
        }

        int lastIndex = 0;
        int litteralIndex = 0;// This index is used to determine the position of litterals
        String queryString = getQueryString();
        Writer writer = new CharArrayWriter(queryString.length() + 50);
        try {
            // ** This method is heavily optimized do not touch anyhthing unless you "know" what your doing.
            while (lastIndex != -1) {
                int poundIndex = queryString.indexOf('#", lastIndex);
                String token;
                if (poundIndex == -1) {
                    token = queryString.substring(lastIndex, queryString.length());
                    lastIndex = -1;
                } else {
                    token = queryString.substring(lastIndex, poundIndex);
                }
                writer.write(token);
                if (poundIndex != -1) {
                    int wordEndIndex = poundIndex + 1;
                    while ((wordEndIndex < queryString.length()) && (whitespace().indexOf(queryString.charAt(wordEndIndex)) == -1)) {
                        wordEndIndex = wordEndIndex + 1;
                    }

                    // Check for ## which means field from modify row.
                    if (queryString.charAt(poundIndex + 1) == '#") {
                        // Check for ### which means OUT parameter type.
                        if (queryString.charAt(poundIndex + 2) == '#") {
                            // Check for #### which means INOUT parameter type.
                            if (queryString.charAt(poundIndex + 3) == '#") {
                                String fieldName = queryString.substring(poundIndex + 4, wordEndIndex);
                                DatabaseField field = createField(fieldName);
                                appendInOut(writer, field);
                            } else {
                                String fieldName = queryString.substring(poundIndex + 3, wordEndIndex);
                                DatabaseField field = createField(fieldName);
                                appendOut(writer, field);
                            }
                        } else {
                            String fieldName = queryString.substring(poundIndex + 2, wordEndIndex);
                            DatabaseField field = createField(fieldName);
                            appendModify(writer, field);
                        }
                    } else {
                        String fieldName = queryString.substring(poundIndex + 1, wordEndIndex);
                        DatabaseField field = createField(fieldName);
                        appendIn(writer, field);
                    }
                    lastIndex = wordEndIndex;
                }
            }
            setQueryString(writer.toString());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
    
public voidtranslatePureSQLCustomQuery()
INTERNAL: Parse the query string for # markers for custom query based on a query language. This is used by SQLCall and XQuery call, but can be reused by other query languages.

        int lastIndex = 0;
        String queryString = getQueryString();
        int parameterIndex = 1; // this is the parameter index
        Writer writer = new CharArrayWriter(queryString.length() + 50);
        try {
            // ** This method is heavily optimized do not touch anyhthing unless you "know" what your doing.
            while (lastIndex != -1) {
                int markIndex = queryString.indexOf('?", lastIndex);
                String token;
                if (markIndex == -1) { // did not find question mark then we are done looking
                    token = queryString.substring(lastIndex, queryString.length()); //write rest of sql
                    lastIndex = -1;
                } else {
                    token = queryString.substring(lastIndex, markIndex);
                    lastIndex = markIndex + 1;
                }
                writer.write(token);
                if (markIndex != -1) {  // found the question mark now find the named token
                    int wordEndIndex = markIndex + 1;
                    while ((wordEndIndex < queryString.length()) && (whitespace().indexOf(queryString.charAt(wordEndIndex)) == -1)) {
                        wordEndIndex = wordEndIndex + 1;
                    }
                    if (wordEndIndex > markIndex + 1){ //found a 'name' for this token (may be positional)
                        String fieldName = queryString.substring(markIndex + 1, wordEndIndex);
                        DatabaseField field = createField(fieldName);
                        appendIn(writer, field);
                        lastIndex = wordEndIndex;
                    }else{
                        DatabaseField field = createField(String.valueOf(parameterIndex));
                        parameterIndex++;
                        appendIn(writer, field);
                    }
                }
            }
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        setQueryString(writer.toString());
    
public voidtranslateQueryString(oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow, oracle.toplink.essentials.internal.sessions.AbstractRecord modifyRow, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Allow the call to translate from the translation for predefined calls.

        if (getQueryString().indexOf(argumentMarker()) == -1) {
            return;
        }

        //has a '?'
        if (getParameters().isEmpty()) {
            //has no parameters
            return;
        }

        int lastIndex = 0;
        int parameterIndex = 0;
        String queryString = getQueryString();
        Writer writer = new CharArrayWriter(queryString.length() + 50);
        try {
            // ** This method is heavily optimized do not touch anyhthing unless you know "very well" what your doing!!
            // Must translate field parameters and may get new bound parameters for large data.
            Vector parameterFields = getParameters();
            setParameters(null);
            while (lastIndex != -1) {
                int tokenIndex = queryString.indexOf(argumentMarker(), lastIndex);
                String token;
                if (tokenIndex == -1) {
                    token = queryString.substring(lastIndex, queryString.length());
                    lastIndex = -1;
                } else {
                    token = queryString.substring(lastIndex, tokenIndex);
                }
                writer.write(token);
                if (tokenIndex != -1) {
                    // Process next parameter.
                    Integer parameterType = (Integer)getParameterTypes().elementAt(parameterIndex);
                    if (parameterType == MODIFY) {
                        DatabaseField field = (DatabaseField)parameterFields.elementAt(parameterIndex);
                        Object value = modifyRow.get(field);
                        appendParameter(writer, value, session);
                    } else if (parameterType == CUSTOM_MODIFY) {
                        DatabaseField field = (DatabaseField)parameterFields.elementAt(parameterIndex);
                        Object value = modifyRow.get(field);
                        if (value != null) {
                            value = session.getDatasourcePlatform().getCustomModifyValueForCall(this, value, field, false);
                        }
                        appendParameter(writer, value, session);
                    } else if (parameterType == TRANSLATION) {
                        Object parameter = parameterFields.elementAt(parameterIndex);
                        Object value = null;

                        // Parameter expressions are used for nesting and correct mapping conversion of the value.
                        if (parameter instanceof ParameterExpression) {
                            value = ((ParameterExpression)parameter).getValue(translationRow, session);
                        } else {
                            DatabaseField field = (DatabaseField)parameter;
                            value = translationRow.get(field);
                            // Must check for the modify row as well for custom SQL compatibility as only one # is required.
                            if ((value == null) && (modifyRow != null)) {
                                value = modifyRow.get(field);
                            }
                        }
                        appendParameter(writer, value, session);
                    } else if (parameterType == LITERAL) {
                        Object value = parameterFields.elementAt(parameterIndex);
                        if(value instanceof DatabaseField) {
                            value = null;
                        }
                        appendParameter(writer, value, session);
                    } else if (parameterType == IN) {
                        Object parameter = parameterFields.elementAt(parameterIndex);
                        Object value = getValueForInParameter(parameter, translationRow, modifyRow, session, false);
                        appendParameter(writer, value, session);
                    } else if (parameterType == INOUT) {
                        Object parameter = parameterFields.elementAt(parameterIndex);
                        Object value = getValueForInOutParameter(parameter, translationRow, modifyRow, session);
                        appendParameter(writer, value, session);
                    }
                    lastIndex = tokenIndex + 1;
                    parameterIndex++;
                }
            }

            setQueryString(writer.toString());

        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
    
protected java.lang.Stringwhitespace()
INTERNAL: Return the characters that represent non-arguments names.

        return ",); \n\t:";