Package org.eclipse.persistence.tools.dbws.oracle

Source Code of org.eclipse.persistence.tools.dbws.oracle.PLSQLHelperObjectsBuilder

/*******************************************************************************
* Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
*     Mike Norman - from Proof-of-concept, become production code
******************************************************************************/
package org.eclipse.persistence.tools.dbws.oracle;

//javase imports
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;

//EclipseLink
import org.eclipse.persistence.internal.helper.ComplexDatabaseType;
import org.eclipse.persistence.internal.helper.DatabaseType;
import org.eclipse.persistence.platform.database.jdbc.JDBCTypes;
import org.eclipse.persistence.platform.database.oracle.jdbc.OracleArrayType;
import org.eclipse.persistence.platform.database.oracle.jdbc.OracleObjectType;
import org.eclipse.persistence.platform.database.oracle.plsql.OraclePLSQLTypes;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLCollection;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLargument;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLrecord;
import org.eclipse.persistence.platform.database.oracle.publisher.visit.PublisherDefaultListener;
import org.eclipse.persistence.tools.dbws.DBWSBuilder;
import org.eclipse.persistence.tools.dbws.ProcedureOperationModel;

import static org.eclipse.persistence.internal.xr.XRDynamicClassLoader.COLLECTION_WRAPPER_SUFFIX;

public class PLSQLHelperObjectsBuilder extends PublisherDefaultListener {

    protected Map<String, DatabaseType[]> methodTypeMap = new HashMap<String, DatabaseType[]>();
    protected Map<String, DatabaseType> knownDatabaseTypesMap = new HashMap<String, DatabaseType>();
    protected Stack<DatabaseType> typeStack = new Stack<DatabaseType>();
    protected String packageName = null;
    protected String schemaName = null;
    protected String currentMethodName = null;
    protected int currentMethodArgIdx = -1;
    protected DBWSBuilder dbwsBuilder;
    protected ProcedureOperationModel opModel;
    protected boolean processingMethodReturnType = false;

    public PLSQLHelperObjectsBuilder(DBWSBuilder dbwsBuilder) {
        this(dbwsBuilder, null);
    }
    public PLSQLHelperObjectsBuilder(DBWSBuilder dbwsBuilder, ProcedureOperationModel opModel) {
        this.dbwsBuilder = dbwsBuilder;
        this.opModel = opModel;
    }

    public String trimOffSchemaName(String s) {
        if (schemaName != null) {
            if (s.startsWith(schemaName)) {
                return s.substring(schemaName.length() + 1);
            }
        }
        return s;
    }

    public DatabaseType[] getTypesForMethod(String methodName) {
        return methodTypeMap.get(methodName);
    }

    public Map<String, DatabaseType[]> getMethodTypeMap() {
        return methodTypeMap;
    }

    public DatabaseType getKnownDatabaseType(String typeName) {
        return knownDatabaseTypesMap.get(typeName);
    }

    public void putKnownDatabaseType(String typeName, DatabaseType databaseType) {
        knownDatabaseTypesMap.put(typeName, databaseType);
    }

    @Override
    public void beginPackage(String packageName) {
        // trim-off schema name
        int dotIdx = packageName.indexOf('.');
        if (dotIdx > -1) {
            schemaName = packageName.substring(0, dotIdx);
            this.packageName = packageName.substring(dotIdx + 1);
        }
    }

    @Override
    public void beginPlsqlTable(String tableName, String targetTypeName) {
        PLSQLCollection plsqlCollection = null;
        boolean found = false;
        for (DatabaseType[] databaseTypes : methodTypeMap.values()) {
            if (found) {
                break;
            }
            for (int i = 0, len = databaseTypes.length; i < len; i++) {
                DatabaseType databaseType = databaseTypes[i];
                if (databaseType != null && databaseType.isComplexDatabaseType()) {
                    ComplexDatabaseType cdt = (ComplexDatabaseType)databaseType;
                    if (cdt.isCollection()) {
                        PLSQLCollection tmp = (PLSQLCollection)cdt;
                        if (tmp.getCompatibleType().equalsIgnoreCase(targetTypeName)) {
                            found = true;
                            plsqlCollection = tmp;
                            break;
                        }
                    }
                }
            }
        }
        if (plsqlCollection == null) {
            plsqlCollection = new PLSQLCollection();
            plsqlCollection.setTypeName(trimOffSchemaName(tableName));
            plsqlCollection.setCompatibleType(targetTypeName);
            putKnownDatabaseType(tableName, plsqlCollection);
        }
        typeStack.push(plsqlCollection);
    }

    @Override
    public void endPlsqlTable(String tableName, String typeDeclaration, String typeDropDDL) {
        if (!"".equals(typeDeclaration)) {
            dbwsBuilder.getTypeDDL().add(typeDeclaration);
            dbwsBuilder.getTypeDropDDL().add(typeDropDDL);
        }
        PLSQLCollection plsqlCollection = (PLSQLCollection)typeStack.pop();
        plsqlCollection.setJavaTypeName(
            plsqlCollection.getTypeName().toLowerCase() + COLLECTION_WRAPPER_SUFFIX);
        if (!typeStack.empty()) {
            DatabaseType top = typeStack.peek();
            if (top.isComplexDatabaseType()) {
                ComplexDatabaseType cdt = (ComplexDatabaseType)top;
                if (cdt.isCollection()) {
                    ((PLSQLCollection)cdt).setNestedType(plsqlCollection);
                }
                else if (cdt.isRecord()) {
                    List<PLSQLargument> fields = ((PLSQLrecord)cdt).getFields();
                    PLSQLargument field = fields.get(fields.size() - 1);
                    if (field.databaseType == null) {
                        field.databaseType = plsqlCollection;
                    }
                }
            }
        }
        else {
            typeStack.push(plsqlCollection);
        }
    }

    @Override
    public void beginPlsqlRecord(String plsqlRecordName, String targetTypeName, int numFields) {
        PLSQLrecord plsqlRecord = null;
        boolean found = false;
        for (DatabaseType[] databaseTypes : methodTypeMap.values()) {
            if (found) {
                break;
            }
            for (int i = 0, len = databaseTypes.length; i < len; i++) {
                DatabaseType databaseType = databaseTypes[i];
                if (databaseType != null && databaseType.isComplexDatabaseType()) {
                    ComplexDatabaseType cdt = (ComplexDatabaseType)databaseType;
                    if (cdt.isRecord()) {
                        PLSQLrecord tmp = (PLSQLrecord)cdt;
                        if (tmp.getCompatibleType().equalsIgnoreCase(targetTypeName)) {
                            found = true;
                            plsqlRecord = tmp;
                            break;
                        }
                    }
                }
            }
        }
        if (plsqlRecord == null) {
            plsqlRecord = new PLSQLrecord();
            plsqlRecord.setTypeName(trimOffSchemaName(plsqlRecordName));
            plsqlRecord.setCompatibleType(targetTypeName);
            plsqlRecord.setJavaTypeName(plsqlRecord.getTypeName().toLowerCase());
            putKnownDatabaseType(plsqlRecordName, plsqlRecord);
        }
        typeStack.push(plsqlRecord);
    }

    @Override
    public void beginPlsqlRecordField(String fieldName, int idx) {
        PLSQLrecord plsqlRecord = (PLSQLrecord)typeStack.peek();
        boolean found = false;
        for (PLSQLargument arg : plsqlRecord.getFields()) {
            if (arg.name.equalsIgnoreCase(fieldName)) {
                found = true;
                break;
            }
        }
        if (!found) {
            plsqlRecord.addField(fieldName, null);
        }
    }

    @Override
    public void endPlsqlRecord(String plsqlRecordName, String typeDeclaration, String typeDropDDL) {
        if (!"".equals(typeDeclaration)) {
            dbwsBuilder.getTypeDDL().add(typeDeclaration);
            dbwsBuilder.getTypeDropDDL().add(typeDropDDL);
        }
        PLSQLrecord plsqlRecord = (PLSQLrecord)typeStack.pop();
        if (!typeStack.empty()) {
            DatabaseType top = typeStack.peek();
            if (top.isComplexDatabaseType()) {
                ComplexDatabaseType cdt = (ComplexDatabaseType)top;
                if (cdt.isCollection()) {
                    PLSQLCollection coll = (PLSQLCollection)cdt;
                    if (coll.getNestedType() == null) {
                        coll.setNestedType(plsqlRecord);
                    }
                }
                else if (cdt.isRecord()) {
                    PLSQLrecord rec = (PLSQLrecord)cdt;
                    List<PLSQLargument> fields = rec.getFields();
                    PLSQLargument arg = fields.get(fields.size() - 1);
                    if (arg.databaseType == null) {
                        arg.databaseType = plsqlRecord;
                    }
                }
            }
        }
        else {
            typeStack.push(plsqlRecord);
        }
    }

    @Override
    public void beginMethod(String methodName, int numArgs) {
        methodTypeMap.put(methodName, new DatabaseType[numArgs]);
        currentMethodName = methodName;
    }

    @Override
    public void beginMethodArg(String argName, String direction, int idx) {
        currentMethodArgIdx = idx;
        //  may have processed a return type (stored function)
        if (processingMethodReturnType) {
            processingMethodReturnType = false;
            if (opModel != null && !typeStack.empty()) {
                opModel.setDbStoredFunctionReturnType(typeStack.pop());
            }
        }
    }

    @Override
    public void endMethodArg(String argName) {
        DatabaseType[] methodType = methodTypeMap.get(currentMethodName);
        methodType[currentMethodArgIdx] = typeStack.pop();
    }

    @Override
    public void endMethod(String methodName) {
        if (opModel != null) {
            opModel.addArgumentTypes(methodTypeMap.get(methodName));
            // handle case where we have processed a  return
            // type for a stored function with no input args
            if (processingMethodReturnType) {
                processingMethodReturnType = false;
                if (!typeStack.empty()) {
                    opModel.setDbStoredFunctionReturnType(typeStack.pop());
                }
            }
        }
        currentMethodName = null;
        currentMethodArgIdx = -1;
    }
   
    @Override
    public void handleMethodReturn(String returnTypeName) {
        processingMethodReturnType = true;
    }
   
    @Override
    public void handleSqlType(String sqlTypeName, int typecode, String targetType) {
        DatabaseType databaseType = JDBCTypes.getDatabaseTypeForCode(typecode);
        if (databaseType == null) {
            databaseType = OraclePLSQLTypes.getDatabaseTypeForCode(
                trimOffSchemaName(sqlTypeName));
            if (databaseType == null) {
                databaseType = getKnownDatabaseType(sqlTypeName);
            }
        }
        if (!typeStack.empty()) {
            DatabaseType top = typeStack.peek();
            if (top.isComplexDatabaseType()) {
                ComplexDatabaseType cdt = (ComplexDatabaseType)top;
                if (cdt.isCollection()) {
                    if (cdt.isJDBCType()) {
                        //TODO Oracle Varray
                    }
                    else {
                        PLSQLCollection coll = (PLSQLCollection)cdt;
                        if (coll.getNestedType() == null) {
                            coll.setNestedType(databaseType);
                        }
                    }
                }
                else {
                    if (cdt.isRecord()) {
                        PLSQLrecord rec = (PLSQLrecord)cdt;
                        List<PLSQLargument> fields = rec.getFields();
                        PLSQLargument arg = fields.get(fields.size() - 1);
                        if (arg.databaseType == null) {
                            arg.databaseType = databaseType;
                        }
                    }
                    else if (cdt.isJDBCType()) {
                        OracleObjectType oot = (OracleObjectType)cdt;
                        Map<String, DatabaseType> fields = oot.getFields();
                        Object[] keys = oot.getFields().keySet().toArray();
                        String lastInsertedKey = (String)keys[oot.getLastFieldIndex()];
                        fields.put(lastInsertedKey, databaseType);
                    }
                }
            }
        }
        else {
            typeStack.push(databaseType);
        }
    }

    @Override
    public void beginObjectType(final String objectTypename) {
        DatabaseType databaseType = OraclePLSQLTypes.getDatabaseTypeForCode(
            trimOffSchemaName(objectTypename));
        if (databaseType == null) {
            databaseType = getKnownDatabaseType(objectTypename);
        }
        if (databaseType == null) {
            OracleObjectType objectType = new OracleObjectType();
            objectType.setTypeName(objectTypename);
            DatabaseType top = typeStack.peek();
            if (top.isComplexDatabaseType()) {
                ComplexDatabaseType cdt = (ComplexDatabaseType)top;
                if (cdt.isJDBCType()) {
                    if (cdt.isCollection()) {
                        OracleArrayType oat = (OracleArrayType)cdt;
                        oat.setNestedType(objectType);
                    }
                    else {
                        OracleObjectType oot = (OracleObjectType)cdt;
                        Map<String, DatabaseType> fields = oot.getFields();
                        Object[] keys = oot.getFields().keySet().toArray();
                        String lastInsertedKey = (String)keys[oot.getLastFieldIndex()];
                        if (fields.get(lastInsertedKey) == JDBCTypes.NULL_TYPE) {
                            // nested OracleObjectTypes
                            fields.put(lastInsertedKey, objectType);
                        }
                    }
                }
            }
            typeStack.push(objectType);
            putKnownDatabaseType(objectTypename, objectType);
        }
    }

    @Override
    public void handleObjectType(String objectTypename, String targetTypeName, int numAttributes) {
        DatabaseType databaseType = OraclePLSQLTypes.getDatabaseTypeForCode(
            trimOffSchemaName(objectTypename));
        if (databaseType == null) {
            databaseType = getKnownDatabaseType(objectTypename);
        }
        if (!typeStack.empty()) {
            DatabaseType top = typeStack.peek();
            if (top.isComplexDatabaseType()) {
                ComplexDatabaseType cdt = (ComplexDatabaseType)top;
                if (cdt.isCollection()) {
                    PLSQLCollection coll = (PLSQLCollection)cdt;
                    if (coll.getNestedType() == null) {
                        coll.setNestedType(databaseType);
                    }
                }
                else if (cdt.isRecord()) {
                    PLSQLrecord rec = (PLSQLrecord)cdt;
                    List<PLSQLargument> fields = rec.getFields();
                    PLSQLargument arg = fields.get(fields.size() - 1);
                    if (arg.databaseType == null) {
                        arg.databaseType = databaseType;
                    }
                }
                else if (cdt.isJDBCType()) {
                    if (typeStack.size() > 1) {
                        typeStack.pop();
                        DatabaseType topMinus1 = typeStack.peek();
                        if (topMinus1.isComplexDatabaseType()) {
                            ComplexDatabaseType cdtMinus1 = (ComplexDatabaseType)topMinus1;
                            if (cdtMinus1.isRecord()) {
                                PLSQLrecord rec = (PLSQLrecord)cdtMinus1;
                                List<PLSQLargument> fields = rec.getFields();
                                PLSQLargument arg = fields.get(fields.size() - 1);
                                if (arg.databaseType == null) {
                                    arg.databaseType = cdt;
                                }
                            }
                        }
                        typeStack.push(top);
                    }
                }
            }
        }
        else {
            typeStack.push(databaseType);
        }
    }

    @Override
    public void handleAttributeField(String attributeFieldName, int idx) {
        if (!typeStack.empty()) {
            DatabaseType top = typeStack.peek();
            if (top.isComplexDatabaseType() && top.isJDBCType()) {
                ComplexDatabaseType cdt = (ComplexDatabaseType)top;
                OracleObjectType oot = (OracleObjectType)cdt;
                oot.getFields().put(attributeFieldName, JDBCTypes.NULL_TYPE); // placeholder
                oot.setLastFieldIndex(idx);
            }
        }
    }

    @Override
    public void endObjectType(String objectTypename) {
        DatabaseType databaseType = OraclePLSQLTypes.getDatabaseTypeForCode(
           trimOffSchemaName(objectTypename));
        if (databaseType == null) {
            DatabaseType top = typeStack.peek();
            if (top.getTypeName().equals(objectTypename)) {
                typeStack.pop();
            }
        }
    }

    @Override
    public void handleSqlArrayType(String name, String targetTypeName) {
        DatabaseType databaseType = OraclePLSQLTypes.getDatabaseTypeForCode(
            trimOffSchemaName(name));
        if (databaseType == null) {
            databaseType = getKnownDatabaseType(name);
        }
        if (databaseType == null) {
            OracleArrayType oat = new OracleArrayType();
            oat.setTypeName(name);
            typeStack.push(oat);
            putKnownDatabaseType(name, oat);
        }
        else {
            typeStack.push(databaseType);
        }
    }

    @Override
    public void endPlsqlRecordField(String fieldName, int idx) {
        if (!typeStack.empty()) {
            DatabaseType top = typeStack.peek();
            if (top.isComplexDatabaseType()) {
                ComplexDatabaseType cdt = (ComplexDatabaseType)top;
                if (cdt.isJDBCType() && cdt.isCollection()) {
                    // take OracleArrayType off stack
                    DatabaseType pop = typeStack.pop();
                    if (!typeStack.isEmpty()) {
                        DatabaseType topMinus1 = typeStack.peek();
                        if (topMinus1.isComplexDatabaseType()) {
                            ComplexDatabaseType cdtMinus1 = (ComplexDatabaseType)topMinus1;
                            if (cdtMinus1.isRecord()) {
                                PLSQLrecord recMinus1 = (PLSQLrecord)cdtMinus1;
                                PLSQLargument arg = null;
                                for (Iterator<PLSQLargument> i = recMinus1.getFields().iterator(); i.hasNext();) {
                                    arg = i.next();
                                    if (arg.name.equalsIgnoreCase(fieldName)) {
                                        break;
                                    }
                                }
                                if (arg != null && arg.databaseType == null) {
                                    arg.databaseType = pop;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
TOP

Related Classes of org.eclipse.persistence.tools.dbws.oracle.PLSQLHelperObjectsBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.