| /* |
| * Copyright (c) 1998, 2021 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 v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Mike Norman - from Proof-of-concept, become production code |
| package org.eclipse.persistence.tools.dbws.oracle; |
| |
| import static java.sql.Types.ARRAY; |
| import static java.sql.Types.OTHER; |
| import static java.sql.Types.STRUCT; |
| import static java.util.logging.Level.FINEST; |
| // EclipseLink imports |
| import static org.eclipse.persistence.internal.oxm.Constants.ANY_QNAME; |
| import static org.eclipse.persistence.internal.oxm.Constants.COLON; |
| import static org.eclipse.persistence.internal.oxm.Constants.DATE_QNAME; |
| import static org.eclipse.persistence.internal.oxm.Constants.DOT; |
| import static org.eclipse.persistence.internal.oxm.Constants.EMPTY_STRING; |
| import static org.eclipse.persistence.internal.oxm.Constants.INT; |
| import static org.eclipse.persistence.internal.oxm.Constants.SCHEMA_INSTANCE_PREFIX; |
| import static org.eclipse.persistence.internal.oxm.Constants.SCHEMA_PREFIX; |
| import static org.eclipse.persistence.internal.oxm.Constants.TEXT; |
| import static org.eclipse.persistence.internal.xr.Util.SXF_QNAME; |
| import static org.eclipse.persistence.internal.xr.Util.getClassFromJDBCType; |
| import static org.eclipse.persistence.internal.xr.Util.getJDBCTypeForTypeName; |
| import static org.eclipse.persistence.internal.xr.XRDynamicClassLoader.COLLECTION_WRAPPER_SUFFIX; |
| import static org.eclipse.persistence.oxm.XMLConstants.SCHEMA_INSTANCE_URL; |
| import static org.eclipse.persistence.oxm.XMLConstants.SCHEMA_URL; |
| import static org.eclipse.persistence.oxm.mappings.nullpolicy.XMLNullRepresentationType.XSI_NIL; |
| import static org.eclipse.persistence.tools.dbws.Util.APP_OCTET_STREAM; |
| import static org.eclipse.persistence.tools.dbws.Util.AT_SIGN; |
| import static org.eclipse.persistence.tools.dbws.Util.BUILDING_QUERYOP_FOR; |
| import static org.eclipse.persistence.tools.dbws.Util.CLOSE_PAREN; |
| import static org.eclipse.persistence.tools.dbws.Util.CURSOR_OF_STR; |
| import static org.eclipse.persistence.tools.dbws.Util.CURSOR_STR; |
| import static org.eclipse.persistence.tools.dbws.Util.OPEN_PAREN; |
| import static org.eclipse.persistence.tools.dbws.Util.PERCENT; |
| import static org.eclipse.persistence.tools.dbws.Util.SLASH; |
| import static org.eclipse.persistence.tools.dbws.Util.SXF_QNAME_CURSOR; |
| import static org.eclipse.persistence.tools.dbws.Util.TOPLEVEL; |
| import static org.eclipse.persistence.tools.dbws.Util.TYPE_STR; |
| import static org.eclipse.persistence.tools.dbws.Util.UNDERSCORE; |
| import static org.eclipse.persistence.tools.dbws.Util.XMLTYPE_STR; |
| import static org.eclipse.persistence.tools.dbws.Util.buildCustomQName; |
| import static org.eclipse.persistence.tools.dbws.Util.getAttributeClassForDatabaseType; |
| import static org.eclipse.persistence.tools.dbws.Util.getGeneratedAlias; |
| import static org.eclipse.persistence.tools.dbws.Util.getGeneratedJavaClassName; |
| import static org.eclipse.persistence.tools.dbws.Util.getXMLTypeFromJDBCType; |
| import static org.eclipse.persistence.tools.dbws.Util.hasComplexArgs; |
| import static org.eclipse.persistence.tools.dbws.Util.hasPLSQLCursorArg; |
| import static org.eclipse.persistence.tools.dbws.Util.qNameFromString; |
| import static org.eclipse.persistence.tools.dbws.Util.shouldSetJavaType; |
| import static org.eclipse.persistence.tools.dbws.Util.sqlMatch; |
| import static org.eclipse.persistence.tools.oracleddl.metadata.ArgumentTypeDirection.IN; |
| import static org.eclipse.persistence.tools.oracleddl.metadata.ArgumentTypeDirection.INOUT; |
| import static org.eclipse.persistence.tools.oracleddl.metadata.ArgumentTypeDirection.OUT; |
| |
| import java.sql.Array; |
| import java.sql.Struct; |
| import java.sql.Types; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.Vector; |
| import java.util.logging.Level; |
| |
| import javax.xml.namespace.QName; |
| |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| import org.eclipse.persistence.internal.core.helper.CoreClassConstants; |
| import org.eclipse.persistence.internal.helper.ClassConstants; |
| import org.eclipse.persistence.internal.helper.ComplexDatabaseType; |
| import org.eclipse.persistence.internal.helper.DatabaseField; |
| import org.eclipse.persistence.internal.helper.StringHelper; |
| import org.eclipse.persistence.internal.oxm.XMLConversionManager; |
| import org.eclipse.persistence.internal.xr.Attachment; |
| import org.eclipse.persistence.internal.xr.CollectionResult; |
| import org.eclipse.persistence.internal.xr.NamedQueryHandler; |
| import org.eclipse.persistence.internal.xr.Parameter; |
| import org.eclipse.persistence.internal.xr.ProcedureArgument; |
| import org.eclipse.persistence.internal.xr.ProcedureOutputArgument; |
| import org.eclipse.persistence.internal.xr.QueryHandler; |
| import org.eclipse.persistence.internal.xr.QueryOperation; |
| import org.eclipse.persistence.internal.xr.Result; |
| import org.eclipse.persistence.internal.xr.StoredFunctionQueryHandler; |
| import org.eclipse.persistence.internal.xr.StoredProcedureQueryHandler; |
| import org.eclipse.persistence.mappings.DirectToFieldMapping; |
| import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping; |
| import org.eclipse.persistence.mappings.structures.ArrayMapping; |
| import org.eclipse.persistence.mappings.structures.ObjectArrayMapping; |
| import org.eclipse.persistence.mappings.structures.ObjectRelationalDataTypeDescriptor; |
| import org.eclipse.persistence.mappings.structures.ObjectRelationalDatabaseField; |
| import org.eclipse.persistence.mappings.structures.StructureMapping; |
| import org.eclipse.persistence.oxm.NamespaceResolver; |
| import org.eclipse.persistence.oxm.XMLDescriptor; |
| import org.eclipse.persistence.oxm.XMLField; |
| import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping; |
| import org.eclipse.persistence.oxm.mappings.XMLCompositeDirectCollectionMapping; |
| import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping; |
| import org.eclipse.persistence.oxm.mappings.XMLDirectMapping; |
| import org.eclipse.persistence.oxm.mappings.nullpolicy.AbstractNullPolicy; |
| import org.eclipse.persistence.oxm.schema.XMLSchemaURLReference; |
| import org.eclipse.persistence.platform.database.jdbc.JDBCTypes; |
| import org.eclipse.persistence.platform.database.oracle.jdbc.OracleObjectType; |
| import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLCollection; |
| import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredFunctionCall; |
| import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredProcedureCall; |
| import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLargument; |
| import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLrecord; |
| import org.eclipse.persistence.queries.DataReadQuery; |
| import org.eclipse.persistence.queries.DatabaseQuery; |
| import org.eclipse.persistence.queries.StoredFunctionCall; |
| import org.eclipse.persistence.queries.StoredProcedureCall; |
| import org.eclipse.persistence.queries.ValueReadQuery; |
| import org.eclipse.persistence.sessions.Project; |
| import org.eclipse.persistence.tools.dbws.BaseDBWSBuilderHelper; |
| import org.eclipse.persistence.tools.dbws.DBWSBuilder; |
| import org.eclipse.persistence.tools.dbws.DBWSBuilderHelper; |
| import org.eclipse.persistence.tools.dbws.NamingConventionTransformer.ElementStyle; |
| import org.eclipse.persistence.tools.dbws.ProcedureOperationModel; |
| import org.eclipse.persistence.tools.dbws.Util; |
| import org.eclipse.persistence.tools.oracleddl.metadata.ArgumentType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.ArgumentTypeDirection; |
| import org.eclipse.persistence.tools.oracleddl.metadata.CompositeDatabaseType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.DatabaseType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.FieldType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.FunctionType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.ObjectTableType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.ObjectType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLCollectionType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLCursorType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLPackageType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLRecordType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.ProcedureType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.ROWTYPEType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum; |
| import org.eclipse.persistence.tools.oracleddl.metadata.TYPEType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.TableType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.VArrayType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.visit.BaseDatabaseTypeVisitor; |
| import org.eclipse.persistence.tools.oracleddl.metadata.visit.DatabaseTypeVisitor; |
| import org.eclipse.persistence.tools.oracleddl.parser.ParseException; |
| import org.eclipse.persistence.tools.oracleddl.util.DatabaseTypeBuilder; |
| |
| public class OracleHelper extends BaseDBWSBuilderHelper implements DBWSBuilderHelper { |
| |
| protected DatabaseTypeBuilder dtBuilder = new DatabaseTypeBuilder(); |
| public static final String NO_PKG_MSG = "No packages were found matching the following: "; |
| |
| public OracleHelper(DBWSBuilder dbwsBuilder) { |
| super(dbwsBuilder); |
| } |
| |
| /** |
| * Indicates if this helper instance contains one or more |
| * TableType instances in TableType List "dbTables". |
| */ |
| @Override |
| public boolean hasTables() { |
| return dbTables.size() == 0 ? false : true; |
| } |
| |
| @Override |
| public void buildDbArtifacts() { |
| super.buildDbArtifacts(); |
| //list of all directly-referenced packages |
| Set<PLSQLPackageType> directPackages = new HashSet<PLSQLPackageType>(); |
| for (ProcedureType procedureType : dbStoredProcedures) { |
| for (ArgumentType argumentType : procedureType.getArguments()) { |
| DatabaseType argumentDataType = argumentType.getEnclosedType(); |
| if (argumentDataType.isPLSQLType()) { |
| PLSQLType plsqlType = (PLSQLType)argumentDataType; |
| directPackages.add(plsqlType.getParentType()); |
| } |
| } |
| } |
| //any indirectly-referenced packages? |
| final Set<PLSQLPackageType> indirectPackages = new HashSet<PLSQLPackageType>(); |
| DatabaseTypeVisitor indirectVisitor = new BaseDatabaseTypeVisitor() { |
| @Override |
| public void beginVisit(PLSQLPackageType databaseType) { |
| indirectPackages.add(databaseType); |
| } |
| }; |
| for (PLSQLPackageType pckage : directPackages) { |
| pckage.accept(indirectVisitor); |
| } |
| Set<PLSQLPackageType> packages = new HashSet<PLSQLPackageType>(); |
| packages.addAll(directPackages); |
| packages.addAll(indirectPackages); |
| for (PLSQLPackageType pckage : packages) { |
| ShadowDDLGenerator ddlGenerator = new ShadowDDLGenerator(pckage); |
| dbwsBuilder.getTypeDDL().addAll(ddlGenerator.getAllCreateDDLs()); |
| dbwsBuilder.getTypeDropDDL().addAll(ddlGenerator.getAllDropDDLs()); |
| } |
| } |
| |
| /** |
| * Builds query operations for a given ProcedureOperationModel. |
| */ |
| @Override |
| public void buildProcedureOperation(ProcedureOperationModel procedureOperationModel) { |
| for (ProcedureType storedProcedure : procedureOperationModel.getDbStoredProcedures()) { |
| boolean hasComplexArgs = hasComplexArgs(storedProcedure); |
| QueryOperation qo = new QueryOperation(); |
| qo.setName(getNameForQueryOperation(procedureOperationModel, storedProcedure)); |
| |
| String qualifiedProcName = getQualifiedProcedureName(procedureOperationModel, storedProcedure); |
| dbwsBuilder.logMessage(FINEST, BUILDING_QUERYOP_FOR + qualifiedProcName); |
| |
| QueryHandler qh = null; |
| // before assigning queryHandler, check for named query in OR project |
| List<DatabaseQuery> queries = dbwsBuilder.getOrProject().getQueries(); |
| if (queries.size() > 0) { |
| for (DatabaseQuery q : queries) { |
| if (q.getName().equals(qo.getName())) { |
| qh = new NamedQueryHandler(); |
| ((NamedQueryHandler) qh).setName(qo.getName()); |
| } |
| } |
| } |
| if (qh == null) { |
| if (storedProcedure.isFunctionType()) { |
| qh = new StoredFunctionQueryHandler(); |
| } else { |
| qh = new StoredProcedureQueryHandler(); |
| } |
| ((StoredProcedureQueryHandler) qh).setName(qualifiedProcName); |
| } |
| qo.setQueryHandler(qh); |
| |
| String returnType = procedureOperationModel.getReturnType(); |
| boolean isCollection = procedureOperationModel.isCollection(); |
| boolean isSimpleXMLFormat = procedureOperationModel.isSimpleXMLFormat(); |
| Result result = null; |
| |
| /** |
| * For multiple OUT args as well as a stored function with OUT args, we want |
| * the result to be a collection and the type to be "xsd:any". We will |
| * force SimpleXMLFormat for now as well. |
| */ |
| int outArgCount = 0; |
| for (ArgumentType argument : storedProcedure.getArguments()) { |
| ArgumentTypeDirection argDirection = argument.getDirection(); |
| if (argDirection == OUT) { |
| outArgCount++; |
| } |
| } |
| if (outArgCount > 1 || (outArgCount > 0 && storedProcedure.isFunctionType())) { |
| isCollection = true; |
| isSimpleXMLFormat = true; |
| result = new CollectionResult(); |
| result.setType(ANY_QNAME); |
| } else { |
| if (storedProcedure.isFunctionType()) { |
| ArgumentType returnArg = ((FunctionType)storedProcedure).getReturnArgument(); |
| result = buildResultForStoredFunction(returnArg, returnType); |
| // for strongly typed ref cursors we will customize the simple-xml-format |
| // tags to better represent the PL/SQL record/table/column type |
| if (returnArg.getEnclosedType().isPLSQLCursorType()) { |
| customizeSimpleXMLTagNames((PLSQLCursorType) returnArg.getEnclosedType(), procedureOperationModel); |
| } |
| } else if (hasComplexArgs) { |
| if (Util.noOutArguments(storedProcedure)) { |
| result = new Result(); |
| result.setType(new QName(SCHEMA_URL, INT, SCHEMA_PREFIX)); // rowcount |
| } |
| } else { // !hasComplexArgs |
| // if user overrides returnType, assume they're right |
| if (returnType != null) { |
| result = new Result(); |
| result.setType(buildCustomQName(returnType, dbwsBuilder)); |
| } else { |
| if (isCollection) { |
| result = new CollectionResult(); |
| if (isSimpleXMLFormat) { |
| result.setType(SXF_QNAME_CURSOR); |
| } |
| } else { |
| result = new Result(); |
| result.setType(SXF_QNAME); |
| } |
| } |
| } |
| } |
| for (ArgumentType arg : storedProcedure.getArguments()) { |
| String argName = arg.getArgumentName(); |
| if (argName != null) { |
| QName xmlType = null; |
| ProcedureArgument pa = null; |
| ProcedureArgument paShadow = null; // for INOUT's |
| Parameter parm = null; |
| ArgumentTypeDirection direction = arg.getDirection(); |
| if (!hasComplexArgs) { |
| if (arg.getEnclosedType().isPLSQLCursorType()) { |
| PLSQLCursorType cursorType = (PLSQLCursorType)arg.getEnclosedType(); |
| if (cursorType.isWeaklyTyped()) { |
| xmlType = buildCustomQName("SYS_REFCURSOR", dbwsBuilder); |
| } |
| } else { |
| xmlType = getXMLTypeFromJDBCType(Util.getJDBCTypeFromTypeName(arg.getTypeName())); |
| } |
| } else { |
| // handle PL/SQL records and collections |
| if (arg.getEnclosedType().isPLSQLType()) { |
| String packageName = ((PLSQLType) arg.getEnclosedType()).getParentType().getPackageName(); |
| // may need to prepend package name |
| String typeString = (packageName != null && packageName.length() > 0) ? packageName + UNDERSCORE + arg.getTypeName() : arg.getTypeName(); |
| // may need to strip off % |
| typeString = typeString.contains(PERCENT) ? typeString.replace(PERCENT, UNDERSCORE) : typeString; |
| xmlType = buildCustomQName(nct.generateSchemaAlias(typeString), dbwsBuilder); |
| } else if (arg.getEnclosedType().isVArrayType() || arg.getEnclosedType().isObjectType() || arg.getEnclosedType().isObjectTableType()) { |
| // handle advanced JDBC types |
| xmlType = buildCustomQName(nct.generateSchemaAlias(arg.getTypeName()), dbwsBuilder); |
| } else { |
| switch (Util.getJDBCTypeFromTypeName(arg.getTypeName())) { |
| case STRUCT: |
| case ARRAY: |
| String typeString = nct.generateSchemaAlias(arg.getTypeName()); |
| xmlType = buildCustomQName(typeString, dbwsBuilder); |
| break; |
| default : |
| xmlType = getXMLTypeFromJDBCType(Util.getJDBCTypeFromTypeName(arg.getTypeName())); |
| break; |
| } |
| } |
| } |
| if (direction == null || direction == IN) { |
| parm = new Parameter(); |
| parm.setName(argName); |
| parm.setType(xmlType); |
| |
| // handle optional arg |
| parm.setOptional(arg.optional()); |
| |
| pa = new ProcedureArgument(); |
| pa.setName(argName); |
| pa.setParameterName(argName); |
| if (qh instanceof StoredProcedureQueryHandler) { |
| ((StoredProcedureQueryHandler)qh).getInArguments().add(pa); |
| } |
| } else { |
| // the first OUT/INOUT arg determines singleResult vs. collectionResult |
| pa = new ProcedureOutputArgument(); |
| ProcedureOutputArgument pao = (ProcedureOutputArgument)pa; |
| pao.setName(argName); |
| pao.setParameterName(argName); |
| boolean isCursor = arg.isPLSQLCursorType() || arg.getTypeName().contains(CURSOR_STR); |
| |
| // for strongly typed ref cursors we will customize the simple-xml-format |
| // tags to better represent the PL/SQL record/table/column type |
| if (arg.isPLSQLCursorType()) { |
| customizeSimpleXMLTagNames((PLSQLCursorType) arg.getEnclosedType(), procedureOperationModel); |
| } |
| if (isCursor && returnType == null) { // if user overrides returnType, assume they're right |
| pao.setResultType(SXF_QNAME_CURSOR); |
| if (result == null) { |
| result = new CollectionResult(); |
| result.setType(SXF_QNAME_CURSOR); |
| } |
| } else { |
| // if user overrides returnType, assume they're right |
| // Hmm, multiple OUT's gonna be a problem - later! |
| if (returnType != null && !isSimpleXMLFormat) { |
| xmlType = qNameFromString(OPEN_PAREN + dbwsBuilder.getTargetNamespace() + CLOSE_PAREN + returnType, dbwsBuilder.getSchema()); |
| } |
| if (isCursor) { |
| pao.setResultType(new QName(EMPTY_STRING, CURSOR_OF_STR + returnType)); |
| Result newResult = new CollectionResult(); |
| newResult.setType(result.getType()); |
| result = newResult; |
| } else { |
| pao.setResultType(xmlType); |
| } |
| if (result == null) { |
| if (isCollection) { |
| result = new CollectionResult(); |
| } else { |
| result = new Result(); |
| } |
| result.setType(xmlType); |
| } |
| } |
| if (direction == INOUT) { |
| parm = new Parameter(); |
| parm.setName(argName); |
| parm.setType(xmlType); |
| result.setType(xmlType); |
| if (qh instanceof StoredProcedureQueryHandler) { |
| ((StoredProcedureQueryHandler)qh).getInOutArguments().add(pao); |
| } |
| paShadow = new ProcedureArgument(); |
| paShadow.setName(argName); |
| paShadow.setParameterName(argName); |
| } else { // OUT arg |
| if (qh instanceof StoredProcedureQueryHandler) { |
| ((StoredProcedureQueryHandler)qh).getOutArguments().add(pao); |
| } |
| } |
| } |
| // for XMLType, we want the type code to be 'OPAQUE' (2007) |
| if (arg.getEnclosedType() == ScalarDatabaseTypeEnum.XMLTYPE_TYPE) { |
| pa.setJdbcType(getJDBCTypeForTypeName(XMLTYPE_STR)); |
| } |
| if (hasComplexArgs && arg.getEnclosedType().isPLSQLType()) { |
| pa.setComplexTypeName(storedProcedure.getCatalogName() + UNDERSCORE + arg.getTypeName()); |
| if (paShadow != null) { |
| paShadow.setComplexTypeName(pa.getComplexTypeName()); |
| } |
| } |
| if (parm != null) { |
| qo.getParameters().add(parm); |
| } |
| } |
| } |
| if (procedureOperationModel.getBinaryAttachment()) { |
| Attachment attachment = new Attachment(); |
| attachment.setMimeType(APP_OCTET_STREAM); |
| result.setAttachment(attachment); |
| } |
| // the user may want simpleXMLFormat |
| handleSimpleXMLFormat(isSimpleXMLFormat, result, procedureOperationModel); |
| qo.setResult(result); |
| dbwsBuilder.getXrServiceModel().getOperations().put(qo.getName(), qo); |
| } |
| finishProcedureOperation(); |
| } |
| |
| /** |
| * Build and return a Result instance based on a given ProcedureType |
| * and return type name. |
| */ |
| protected Result buildResultForStoredFunction(ArgumentType returnArgument, String returnType) { |
| Result result = null; |
| DatabaseType rargDataType = returnArgument.getEnclosedType(); |
| |
| // handle ref cursor |
| if (rargDataType.isPLSQLCursorType() || returnArgument.getTypeName().contains(CURSOR_STR)) { |
| result = new CollectionResult(); |
| result.setType(SXF_QNAME_CURSOR); |
| } else { |
| result = new Result(); |
| int rargJdbcType = OTHER; |
| if (rargDataType.isComposite()) { |
| if (rargDataType.isObjectType()) { |
| rargJdbcType = STRUCT; |
| } else if (rargDataType.isVArrayType() || rargDataType.isObjectTableType()) { |
| rargJdbcType = ARRAY; |
| } |
| } else { |
| rargJdbcType = Util.getJDBCTypeFromTypeName(returnArgument.getTypeName()); |
| } |
| switch (rargJdbcType) { |
| case OTHER: |
| String returnTypeName; |
| // if user overrides returnType, assume they're right |
| if (returnType != null && returnType.length() > 0) { |
| returnTypeName = returnType; |
| } else { |
| returnType = rargDataType.getTypeName(); |
| // packages only apply to PL/SQL types |
| String packageName = null; |
| if (rargDataType.isPLSQLType()) { |
| packageName = ((PLSQLType) rargDataType).getParentType().getPackageName(); |
| } |
| // may need to prepend a package name |
| returnTypeName = (packageName != null && packageName.length() > 0) ? packageName + UNDERSCORE + returnType : returnType; |
| // may need to strip off % |
| returnTypeName = returnTypeName.contains(PERCENT) ? returnTypeName.replace(PERCENT, UNDERSCORE) : returnTypeName; |
| returnTypeName = nct.generateSchemaAlias(returnTypeName); |
| } |
| result.setType(buildCustomQName(returnTypeName, dbwsBuilder)); |
| break; |
| case STRUCT: |
| case ARRAY: |
| // if user overrides returnType, assume they're right |
| if (returnType == null || returnType.length() == 0) { |
| returnType = rargDataType.getTypeName().toLowerCase().concat(TYPE_STR); |
| } |
| result.setType(buildCustomQName(returnType, dbwsBuilder)); |
| break; |
| default : |
| // scalar types |
| result.setType(getXMLTypeFromJDBCType(rargJdbcType)); |
| break; |
| } |
| } |
| // for XMLType, we want the type code to be 'OPAQUE' (2007) |
| if (rargDataType == ScalarDatabaseTypeEnum.XMLTYPE_TYPE) { |
| result.setJdbcType(getJDBCTypeForTypeName(XMLTYPE_STR)); |
| } |
| return result; |
| } |
| |
| |
| /** |
| * Returns the name to be used for a QueryOperation (or Query) based on a |
| * given ProcedureType and ProcedureOperationModel. |
| * |
| * The returned string will be: |
| * |
| * 1) If the given ProcedureOperationModel 'name' is a non-null & non-empty |
| * string, the returned string will be one of the following: |
| * a) 'modelName' if no pattern matching or overloading |
| * b) 'modelName_procedureName' if pattern matching and no overloading |
| * c) 'modelName_overload' if overloading and no pattern matching |
| * d) 'modelName_procedureName_overload' if pattern matching & overloading |
| * |
| * OR |
| * |
| * 2) If the given ProcedureOperationModel 'name' is a null or empty string, the |
| * returned string will be in the format: 'overload_catalog_schema_procedureName' |
| */ |
| protected String getNameForQueryOperation(ProcedureOperationModel opModel, ProcedureType storedProcedure) { |
| StringBuilder sb = new StringBuilder(); |
| String modelName = opModel.getName(); |
| |
| if (modelName != null && modelName.length() > 0) { |
| sb.append(modelName); |
| // handle pattern matching |
| if (opModel.getProcedurePattern().contains(Util.PERCENT)) { |
| sb.append(UNDERSCORE); |
| sb.append(storedProcedure.getProcedureName()); |
| } |
| // handle overload |
| if (storedProcedure.getOverload() != 0) { |
| sb.append(UNDERSCORE); |
| sb.append(storedProcedure.getOverload()); |
| } |
| } else { |
| if (storedProcedure.getOverload() > 0) { |
| sb.append(storedProcedure.getOverload()); |
| sb.append(UNDERSCORE); |
| } |
| if (storedProcedure.getCatalogName() != null && storedProcedure.getCatalogName().length() > 0) { |
| sb.append(storedProcedure.getCatalogName()); |
| sb.append(UNDERSCORE); |
| } |
| if (storedProcedure.getSchema() != null && storedProcedure.getSchema().length() > 0) { |
| sb.append(storedProcedure.getSchema()); |
| sb.append(UNDERSCORE); |
| } |
| sb.append(storedProcedure.getProcedureName()); |
| } |
| return sb.toString(); |
| } |
| |
| /** |
| * Returns the qualified stored procedure name based on a given ProcedureType |
| * and ProcedureOperationModel. |
| * |
| * The returned string will be in the format: 'schema.catalog.procedureName' |
| * |
| */ |
| protected String getQualifiedProcedureName(ProcedureOperationModel procedureOperationModel, ProcedureType storedProcedure) { |
| StringBuilder sb = new StringBuilder(); |
| if (procedureOperationModel.getSchemaPattern() != null && |
| procedureOperationModel.getSchemaPattern().length() > 0 && |
| storedProcedure.getSchema() != null && |
| storedProcedure.getSchema().length() > 0) { |
| sb.append(storedProcedure.getSchema()); |
| sb.append(DOT); |
| } |
| if (storedProcedure.getCatalogName() != null && storedProcedure.getCatalogName().length() > 0) { |
| sb.append(storedProcedure.getCatalogName()); |
| sb.append(DOT); |
| } |
| sb.append(storedProcedure.getProcedureName()); |
| return sb.toString(); |
| } |
| |
| /** |
| * Generates a {@code List<TableType>} based on a given set of patterns. |
| */ |
| @Override |
| protected List<TableType> loadTables(List<String> catalogPatterns, List<String> schemaPatterns, List<String> tableNamePatterns) { |
| try { |
| return dtBuilder.buildTables(dbwsBuilder.getConnection(), schemaPatterns, tableNamePatterns); |
| } catch (ParseException e) { |
| dbwsBuilder.logMessage(Level.WARNING, e.getMessage()); |
| } |
| return null; |
| } |
| |
| /** |
| * Build list of name patterns separated by vertical bar. |
| * @param namePatterns {@link List} of name patterns. |
| * @return String containing list of name patterns separated by vertical bar. |
| */ |
| private static String buildNamePatternsList(List<String> namePatterns) { |
| final int count = namePatterns.size(); |
| if (count > 0) { |
| int lenhth = count - 1; |
| for (Iterator<String> i = namePatterns.iterator(); i.hasNext(); ) { |
| lenhth += i.next().length(); |
| } |
| StringBuilder out = new StringBuilder(lenhth); |
| for (Iterator<String> i = namePatterns.iterator(); i.hasNext(); ) { |
| out.append(i.next()); |
| if (i.hasNext()) { |
| out.append(StringHelper.VERTICAL_BAR); |
| } |
| } |
| return out.toString(); |
| } else { |
| return StringHelper.EMPTY_STRING; |
| } |
| } |
| |
| /** |
| * Generates a {@code List<ProcedureType>} based on a given set of patterns. |
| */ |
| @Override |
| protected List<ProcedureType> loadProcedures(List<String> catalogPatterns, List<String> schemaPatterns, List<String> procedureNamePatterns) { |
| List<ProcedureType> allProcsAndFuncs = new ArrayList<ProcedureType>(); |
| List<String> topLevelSchemaPatterns = new ArrayList<String>(); |
| List<String> topLevelProcedureNamePatterns = new ArrayList<String>(); |
| Map<String, Set<String>> packagePatterns = new HashMap<String,Set<String>>(); |
| for (int i = 0, len = catalogPatterns.size(); i < len; i++) { |
| String catalogPattern = catalogPatterns.get(i); |
| String schemaPattern = schemaPatterns.get(i); |
| if (schemaPattern == null) { |
| schemaPattern = dbwsBuilder.getUsername().toUpperCase(); |
| } |
| if (catalogPattern == null || catalogPattern.length() == 0 || TOPLEVEL.equals(catalogPattern)) { |
| topLevelSchemaPatterns.add(schemaPattern); |
| topLevelProcedureNamePatterns.add(procedureNamePatterns.get(i)); |
| } else { |
| Set<String> packageNames = packagePatterns.get(schemaPattern); |
| if (packageNames == null) { |
| packageNames = new HashSet<String>(); |
| packagePatterns.put(schemaPattern, packageNames); |
| } |
| packageNames.add(catalogPattern); |
| } |
| } |
| if (topLevelProcedureNamePatterns.size() > 0) { |
| try { |
| List<ProcedureType> topLevelProcedures = dtBuilder.buildProcedures(dbwsBuilder.getConnection(), topLevelSchemaPatterns, topLevelProcedureNamePatterns); |
| if (topLevelProcedures != null && topLevelProcedures.size() > 0) { |
| allProcsAndFuncs.addAll(topLevelProcedures); |
| } |
| } catch (ParseException e) { |
| dbwsBuilder.logMessage(Level.WARNING, e.getMessage()); |
| } |
| try { |
| List<FunctionType> topLevelFunctions = dtBuilder.buildFunctions(dbwsBuilder.getConnection(), topLevelSchemaPatterns, topLevelProcedureNamePatterns); |
| if (topLevelFunctions != null && topLevelFunctions.size() > 0) { |
| allProcsAndFuncs.addAll(topLevelFunctions); |
| } |
| } catch (ParseException e) { |
| dbwsBuilder.logMessage(Level.WARNING, e.getMessage()); |
| } |
| } |
| if (packagePatterns.size() > 0) { |
| try { |
| //unravel map |
| List<String> schemaPats = new ArrayList<String>(); |
| List<String> packagePats = new ArrayList<String>(); |
| for (Map.Entry<String, Set<String>> entry : packagePatterns.entrySet()) { |
| String schema = entry.getKey(); |
| for (String packageName : entry.getValue()) { |
| schemaPats.add(schema); |
| packagePats.add(packageName); |
| } |
| } |
| List<PLSQLPackageType> packages = dtBuilder.buildPackages(dbwsBuilder.getConnection(), schemaPats, packagePats); |
| if (packages == null || packages.isEmpty()) { |
| logPackageNotFoundWarnings(NO_PKG_MSG, schemaPats, packagePats); |
| } else { |
| for (PLSQLPackageType pakage : packages) { |
| //check DDL generation |
| ShadowDDLGenerator ddlGenerator = new ShadowDDLGenerator(pakage); |
| dbwsBuilder.getTypeDDL().addAll(ddlGenerator.getAllCreateDDLs()); |
| dbwsBuilder.getTypeDropDDL().addAll(ddlGenerator.getAllDropDDLs()); |
| //check for overloading |
| Map<String, List<ProcedureType>> overloadMap = new HashMap<String, List<ProcedureType>>(); |
| List<ProcedureType> procedures = pakage.getProcedures(); |
| for (ProcedureType procedure : procedures) { |
| String procedureName = procedure.getProcedureName(); |
| List<ProcedureType> multipleProcedures = overloadMap.get(procedureName); |
| if (multipleProcedures == null) { |
| multipleProcedures = new ArrayList<ProcedureType>(); |
| overloadMap.put(procedureName, multipleProcedures); |
| } |
| multipleProcedures.add(procedure); |
| } |
| for (List<ProcedureType> procs : overloadMap.values()) { |
| if (procs.size() >1) { |
| for (int i = 0, len = procs.size(); i < len; i++) { |
| procs.get(i).setOverload(i); |
| } |
| } |
| } |
| // Check against procedureNamePatterns |
| String tmp = buildNamePatternsList(procedureNamePatterns); |
| for (ProcedureType procedure : procedures) { |
| if (sqlMatch(tmp, procedure.getProcedureName())) { |
| allProcsAndFuncs.add(procedure); |
| } |
| } |
| } |
| } |
| } catch (ParseException e) { |
| dbwsBuilder.logMessage(Level.WARNING, e.getMessage()); |
| } |
| } |
| return allProcsAndFuncs.isEmpty() ? null : allProcsAndFuncs; |
| } |
| |
| /** |
| * Create OR/OX projects for complex types, i.e. PLSQLTypes, VArray, etc. |
| */ |
| @Override |
| public void addToOROXProjectsForComplexTypes(List<CompositeDatabaseType> types, Project orProject, Project oxProject) { |
| for (DatabaseType dbType : types) { |
| String name; |
| String alias; |
| if (dbType.isPLSQLType()) { |
| // set type name to upper case to avoid runtime SQLException |
| dbType.setTypeName(dbType.getTypeName().toUpperCase()); |
| |
| String catalogPattern = ((PLSQLType) dbType).getParentType().getPackageName(); |
| String targetTypeName; |
| // for types enclosed in a ROWTYPEType, package doesn't apply |
| if (catalogPattern == null) { |
| name = dbType.getTypeName(); |
| targetTypeName = dbType.getTypeName(); |
| } else { |
| name = catalogPattern + DOT + dbType.getTypeName(); |
| targetTypeName = catalogPattern + UNDERSCORE + dbType.getTypeName(); |
| } |
| alias = targetTypeName.toLowerCase(); |
| |
| // remove '%' from target, alias, and name |
| name = name.replace(PERCENT, UNDERSCORE); |
| targetTypeName = targetTypeName.replace(PERCENT, UNDERSCORE); |
| alias = alias.replace(PERCENT, UNDERSCORE); |
| |
| // handle PL/SQL record type |
| if (dbType.isPLSQLRecordType()) { |
| addToOXProjectForPLSQLRecordArg(dbType, oxProject, name, alias, targetTypeName, catalogPattern); |
| addToORProjectForPLSQLRecordArg(dbType, orProject, name, alias, targetTypeName, catalogPattern); |
| } // handle PL/SQL collection type |
| else { |
| addToOXProjectForPLSQLTableArg(dbType, oxProject, name, alias, targetTypeName, catalogPattern); |
| addToORProjectForPLSQLTableArg(dbType, orProject, name, alias, targetTypeName, catalogPattern); |
| } |
| } else { |
| // Advanced JDBC types need the (Java) package name prepended to the type name |
| if (Util.isTypeComplex(dbType)) { |
| name = getGeneratedJavaClassName(dbType.getTypeName(), dbwsBuilder.getProjectName()); |
| } else { |
| name = dbType.getTypeName(); |
| } |
| alias = getGeneratedAlias(dbType.getTypeName()); |
| // handle VArray type |
| if (dbType.isVArrayType()) { |
| addToOXProjectForVArrayArg(dbType, oxProject, name, alias); |
| addToORProjectForVArrayArg(dbType, orProject, name, alias); |
| } // handle ObjectType type |
| else if (dbType.isObjectType()) { |
| addToOXProjectForObjectTypeArg(dbType, oxProject, name, alias); |
| addToORProjectForObjectTypeArg(dbType, orProject, name, alias); |
| } // handle ObjectTable type |
| else if (dbType.isObjectTableType()) { |
| addToOXProjectForObjectTableTypeArg(dbType, oxProject, name, alias); |
| addToORProjectForObjectTableTypeArg(dbType, orProject, name, alias); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Build descriptor and mappings for a PL/SQL record argument. The newly |
| * created descriptor will be added to the given OX project. |
| */ |
| protected void addToOXProjectForPLSQLRecordArg(DatabaseType dbType, Project oxProject, String recordName, String recordAlias, String targetTypeName, String catalogPattern) { |
| XMLDescriptor xdesc = (XMLDescriptor) oxProject.getDescriptorForAlias(recordAlias); |
| if (xdesc == null) { |
| xdesc = buildAndAddNewXMLDescriptor(oxProject, recordAlias, recordName.toLowerCase(), nct.generateSchemaAlias(targetTypeName), buildCustomQName(targetTypeName, dbwsBuilder).getNamespaceURI()); |
| } |
| // handle fields |
| PLSQLRecordType plsqlRecType = (PLSQLRecordType) dbType; |
| for (FieldType fType : plsqlRecType.getFields()) { |
| // custom naming transformer may exclude some fields |
| if (nct.styleForElement(fType.getFieldName()) == ElementStyle.NONE) { |
| continue; |
| } |
| String lFieldName = fType.getFieldName().toLowerCase(); |
| if (xdesc.getMappingForAttributeName(lFieldName) == null) { |
| if (fType.isComposite()) { |
| // handle pl/sql record and pl/sql table fields |
| if (fType.getEnclosedType().isPLSQLRecordType()) { |
| buildAndAddXMLCompositeObjectMapping(xdesc, lFieldName, (catalogPattern + DOT + fType.getEnclosedType()).toLowerCase()); |
| } else if (fType.getEnclosedType().isPLSQLCollectionType()) { |
| PLSQLCollectionType tableType = (PLSQLCollectionType) fType.getEnclosedType(); |
| if (tableType.getEnclosedType().isComposite()) { |
| buildAndAddXMLCompositeObjectMapping(xdesc, lFieldName, (catalogPattern + DOT + tableType.getTypeName()).toLowerCase() + COLLECTION_WRAPPER_SUFFIX); |
| } else { |
| Class<?> attributeElementClass = String.class; |
| XMLDescriptor refDesc = (XMLDescriptor) oxProject.getDescriptorForAlias((catalogPattern + UNDERSCORE + tableType.getTypeName()).toLowerCase()); |
| if (refDesc != null) { |
| attributeElementClass = ((XMLCompositeDirectCollectionMapping)refDesc.getMappingForAttributeName(ITEMS_MAPPING_ATTRIBUTE_NAME)).getAttributeElementClass(); |
| } |
| buildAndAddXMLCompositeDirectCollectionMapping(xdesc, lFieldName, lFieldName + SLASH + ITEM_MAPPING_NAME + SLASH + TEXT, attributeElementClass); |
| } |
| } else if (fType.getEnclosedType().isObjectType()) { |
| buildAndAddXMLCompositeObjectMapping(xdesc, lFieldName, getGeneratedJavaClassName(fType.getEnclosedType().getTypeName(), dbwsBuilder.getProjectName())); |
| } else if (fType.getEnclosedType().isVArrayType()) { |
| if (((VArrayType)fType.getEnclosedType()).getEnclosedType().isComposite()) { |
| String nestedTypeAlias = ((VArrayType) fType.getEnclosedType()).getEnclosedType().getTypeName().toLowerCase(); |
| String nestedTypeName = getGeneratedJavaClassName(nestedTypeAlias, dbwsBuilder.getProjectName()); |
| buildAndAddXMLCompositeCollectionMapping(xdesc, lFieldName, lFieldName + SLASH + ITEM_MAPPING_NAME, nestedTypeName); |
| } else { |
| buildAndAddXMLCompositeDirectCollectionMapping(xdesc, lFieldName, lFieldName + SLASH + ITEM_MAPPING_NAME + SLASH + TEXT, getAttributeClassForDatabaseType(fType.getEnclosedType())); |
| } |
| } else if (fType.getEnclosedType().isObjectTableType()) { |
| ObjectTableType nestedType = (ObjectTableType) fType.getEnclosedType(); |
| if (nestedType.getEnclosedType().isComposite()) { |
| String nestedTypeAlias = nestedType.getEnclosedType().getTypeName().toLowerCase(); |
| String nestedTypeName = getGeneratedJavaClassName(nestedTypeAlias, dbwsBuilder.getProjectName()); |
| // ObjectType is composite |
| buildAndAddXMLCompositeCollectionMapping(xdesc, lFieldName, lFieldName + SLASH + ITEM_MAPPING_NAME, nestedTypeName); |
| } else { |
| buildAndAddXMLCompositeDirectCollectionMapping(xdesc, lFieldName, lFieldName + SLASH + TEXT, getAttributeClassForDatabaseType(nestedType)); |
| } |
| } else if (fType.getEnclosedType().isTYPEType()) { // handle %TYPE |
| TYPEType typeType = (TYPEType) fType.getEnclosedType(); |
| if (typeType.getEnclosedType().isFieldType()) { |
| // direct mapping |
| addDirectMappingForFieldType(xdesc, lFieldName, (FieldType)typeType.getEnclosedType()); |
| } |
| } |
| } else { |
| // direct mapping |
| addDirectMappingForFieldType(xdesc, lFieldName, fType); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Build descriptor and mappings for a PL/SQL record argument. The newly |
| * created descriptor will be added to the given OR project. |
| */ |
| @SuppressWarnings("rawtypes") |
| protected void addToORProjectForPLSQLRecordArg(DatabaseType dbType, Project orProject, String recordName, String recordAlias, String targetTypeName, String catalogPattern) { |
| ObjectRelationalDataTypeDescriptor ordtDesc = (ObjectRelationalDataTypeDescriptor) orProject.getDescriptorForAlias(recordAlias); |
| if (ordtDesc == null) { |
| ordtDesc = buildAndAddNewObjectRelationalDataTypeDescriptor(orProject, recordAlias, recordName.toLowerCase()); |
| } |
| // handle fields |
| PLSQLRecordType plsqlRecType = (PLSQLRecordType) dbType; |
| for (FieldType fType : plsqlRecType.getFields()) { |
| String fieldName = fType.getFieldName(); |
| String lFieldName = fieldName.toLowerCase(); |
| // handle field ordering |
| boolean found = false; |
| Vector orderedFields = ordtDesc.getOrderedFields(); |
| for (Iterator i = orderedFields.iterator(); i.hasNext();) { |
| Object o = i.next(); |
| if (o instanceof DatabaseField) { |
| DatabaseField field = (DatabaseField)o; |
| if (field.getName().equalsIgnoreCase(fieldName)) { |
| found = true; |
| break; |
| } |
| } |
| } |
| if (!found) { |
| ordtDesc.addFieldOrdering(fieldName); |
| } |
| if (ordtDesc.getMappingForAttributeName(lFieldName) == null) { |
| if (fType.isComposite()) { |
| if (fType.getEnclosedType().isPLSQLRecordType()) { |
| buildAndAddStructureMapping(ordtDesc, lFieldName, fieldName, recordName.toLowerCase()); |
| } else if (fType.getEnclosedType().isPLSQLCollectionType()) { |
| PLSQLCollectionType tableType = (PLSQLCollectionType) fType.getEnclosedType(); |
| if (tableType.getEnclosedType().isComposite()) { |
| buildAndAddObjectArrayMapping(ordtDesc, lFieldName, fieldName, (catalogPattern + "." + tableType.getTypeName()).toLowerCase() + COLLECTION_WRAPPER_SUFFIX, getStructureNameForField(fType, catalogPattern)); |
| } else { |
| buildAndAddArrayMapping(ordtDesc, lFieldName, fieldName, getStructureNameForField(fType, catalogPattern)); |
| } |
| } else if (fType.getEnclosedType().isObjectType()) { |
| buildAndAddStructureMapping(ordtDesc, lFieldName, fieldName, getGeneratedJavaClassName(fType.getEnclosedType().getTypeName(), dbwsBuilder.getProjectName())); |
| } else if (fType.getEnclosedType().isVArrayType()) { |
| if (((VArrayType)fType.getEnclosedType()).getEnclosedType().isComposite()) { |
| buildAndAddObjectArrayMapping(ordtDesc, lFieldName, fieldName, getGeneratedJavaClassName(((VArrayType)fType.getEnclosedType()).getEnclosedType().getTypeName(), dbwsBuilder.getProjectName()), getStructureNameForField(fType, null)); |
| } else { |
| buildAndAddArrayMapping(ordtDesc, lFieldName, fieldName, getStructureNameForField(fType, null)); |
| } |
| } else if (fType.getEnclosedType().isObjectTableType()) { |
| ObjectTableType nestedType = (ObjectTableType) fType.getEnclosedType(); |
| if (nestedType.getEnclosedType().isComposite()) { |
| ObjectType oType = (ObjectType) nestedType.getEnclosedType(); |
| String oTypeAlias = oType.getTypeName().toLowerCase(); |
| String oTypeName = getGeneratedJavaClassName(oTypeAlias, dbwsBuilder.getProjectName()); |
| // ObjectType is composite |
| buildAndAddObjectArrayMapping(ordtDesc, lFieldName, fieldName, oTypeName, oTypeAlias.toUpperCase()); |
| } else { |
| buildAndAddArrayMapping(ordtDesc, lFieldName, fieldName, nestedType.getTypeName().toUpperCase()); |
| } |
| } else if (fType.getEnclosedType().isTYPEType()) { // handle %TYPE |
| TYPEType typeType = (TYPEType) fType.getEnclosedType(); |
| if (typeType.getEnclosedType().isFieldType()) { |
| // direct mapping |
| AbstractDirectMapping absDirectMapping = (AbstractDirectMapping) ordtDesc.addDirectMapping(lFieldName, fieldName); |
| try { |
| absDirectMapping.setAttributeClassificationName(getClassFromJDBCType(fType.getTypeName(), dbwsBuilder.getDatabasePlatform()).getName()); |
| } catch (Exception x) {} |
| } |
| } |
| } else { |
| // direct mapping |
| DirectToFieldMapping dfm = new DirectToFieldMapping(); |
| dfm.setFieldName(fieldName); |
| dfm.setAttributeName(lFieldName); |
| dfm.setAttributeClassification(getAttributeClassForDatabaseType(fType.getEnclosedType())); |
| ordtDesc.addMapping(dfm); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Build descriptor and mappings for a PL/SQL collection argument. The newly |
| * created descriptor will be added to the given OX project. |
| */ |
| protected void addToOXProjectForPLSQLTableArg(DatabaseType dbType, Project oxProject, String tableName, String tableAlias, String targetTypeName, String catalogPattern) { |
| XMLDescriptor xdesc = (XMLDescriptor) oxProject.getDescriptorForAlias(tableAlias); |
| if (xdesc == null) { |
| xdesc = buildAndAddNewXMLDescriptor(oxProject, tableAlias, tableName.toLowerCase() + COLLECTION_WRAPPER_SUFFIX, nct.generateSchemaAlias(targetTypeName), buildCustomQName(targetTypeName, dbwsBuilder).getNamespaceURI()); |
| } |
| |
| boolean itemsMappingFound = xdesc.getMappingForAttributeName(ITEMS_MAPPING_ATTRIBUTE_NAME) == null ? false : true; |
| if (!itemsMappingFound) { |
| DatabaseType nestedType = ((PLSQLCollectionType)dbType).getEnclosedType(); |
| if (nestedType.isPLSQLRecordType()) { |
| String referenceClassName = (catalogPattern + DOT + ((PLSQLRecordType)nestedType).getTypeName()).toLowerCase(); |
| buildAndAddXMLCompositeCollectionMapping(xdesc, referenceClassName); |
| if (oxProject.getDescriptorForAlias(referenceClassName) == null) { |
| String refTypeName = catalogPattern + UNDERSCORE + ((PLSQLRecordType)nestedType).getTypeName(); |
| addToOXProjectForPLSQLRecordArg(nestedType, oxProject, referenceClassName, refTypeName.toLowerCase(), refTypeName, catalogPattern); |
| } |
| } else if (nestedType.isObjectType()) { |
| buildAndAddXMLCompositeCollectionMapping(xdesc, getGeneratedJavaClassName(nestedType.getTypeName(), dbwsBuilder.getProjectName())); |
| } else { |
| if (nestedType.isComposite()) { |
| buildAndAddXMLCompositeCollectionMapping(xdesc, tableName.toLowerCase() + COLLECTION_WRAPPER_SUFFIX); |
| } else { |
| buildAndAddXMLCompositeDirectCollectionMapping(xdesc, ITEMS_MAPPING_ATTRIBUTE_NAME, ITEM_MAPPING_NAME + SLASH + TEXT, getAttributeClassForDatabaseType(nestedType)); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Build descriptor and mappings for a PL/SQL collection argument. The newly |
| * created descriptor will be added to the given OR project. |
| */ |
| protected void addToORProjectForPLSQLTableArg(DatabaseType dbType, Project orProject, String tableName, String tableAlias, String targetTypeName, String catalogPattern) { |
| ObjectRelationalDataTypeDescriptor ordt = (ObjectRelationalDataTypeDescriptor) orProject.getDescriptorForAlias(tableAlias); |
| if (ordt == null) { |
| ordt = buildAndAddNewObjectRelationalDataTypeDescriptor(orProject, tableAlias, tableName.toLowerCase() + COLLECTION_WRAPPER_SUFFIX); |
| } |
| boolean itemsMappingFound = ordt.getMappingForAttributeName(ITEMS_MAPPING_ATTRIBUTE_NAME) == null ? false : true; |
| if (!itemsMappingFound) { |
| DatabaseType nestedType = ((PLSQLCollectionType) dbType).getEnclosedType(); |
| if (nestedType.isPLSQLRecordType()) { |
| String referenceClassName = (catalogPattern + DOT + ((PLSQLRecordType)nestedType).getTypeName()).toLowerCase(); |
| buildAndAddObjectArrayMapping(ordt, ITEMS_MAPPING_ATTRIBUTE_NAME, ITEMS_MAPPING_FIELD_NAME, referenceClassName, targetTypeName); |
| if (orProject.getDescriptorForAlias(referenceClassName) == null) { |
| String refTypeName = catalogPattern + UNDERSCORE + ((PLSQLRecordType)nestedType).getTypeName(); |
| addToORProjectForPLSQLRecordArg(nestedType, orProject, referenceClassName, refTypeName.toLowerCase(), refTypeName, catalogPattern); |
| } |
| } else if (nestedType.isObjectType()) { |
| buildAndAddObjectArrayMapping(ordt, ITEMS_MAPPING_ATTRIBUTE_NAME, ITEMS_MAPPING_FIELD_NAME, getGeneratedJavaClassName(nestedType.getTypeName(), dbwsBuilder.getProjectName()), targetTypeName); |
| } else { |
| buildAndAddArrayMapping(ordt, ITEMS_MAPPING_ATTRIBUTE_NAME, ITEMS_MAPPING_FIELD_NAME, targetTypeName); |
| } |
| } |
| } |
| |
| /** |
| * Build descriptor and mappings for a VArray argument. The newly |
| * created descriptor will be added to the given OX project. |
| */ |
| protected void addToOXProjectForVArrayArg(DatabaseType dbType, Project oxProject, String arrayName, String arrayAlias) { |
| DatabaseType nestedDbType = ((VArrayType)dbType).getEnclosedType(); |
| String referenceTypeAlias = getGeneratedAlias(nestedDbType.getTypeName()); |
| |
| String referenceTypeName = getGeneratedJavaClassName(referenceTypeAlias, dbwsBuilder.getProjectName()); |
| XMLDescriptor xdesc = (XMLDescriptor)oxProject.getDescriptorForAlias(arrayAlias); |
| if (xdesc == null) { |
| xdesc = buildAndAddNewXMLDescriptor(oxProject, arrayAlias, arrayName + COLLECTION_WRAPPER_SUFFIX, nct.generateSchemaAlias(arrayAlias), buildCustomQName(arrayName, dbwsBuilder).getNamespaceURI()); |
| // before we add this descriptor, check if the nested type's descriptor |
| // should be built and added first |
| XMLDescriptor refXdesc = (XMLDescriptor)oxProject.getDescriptorForAlias(referenceTypeAlias); |
| if (refXdesc == null) { |
| if (nestedDbType.isObjectType()) { |
| addToOXProjectForObjectTypeArg(nestedDbType, oxProject, referenceTypeName, referenceTypeAlias); |
| } |
| } |
| } |
| boolean itemsMappingFound = xdesc.getMappingForAttributeName(ITEMS_MAPPING_ATTRIBUTE_NAME) == null ? false : true; |
| if (!itemsMappingFound) { |
| if (nestedDbType.isComposite()) { |
| buildAndAddXMLCompositeCollectionMapping(xdesc, referenceTypeName); |
| } else { |
| buildAndAddXMLCompositeDirectCollectionMapping(xdesc, ITEMS_MAPPING_ATTRIBUTE_NAME, ITEM_MAPPING_NAME + SLASH + TEXT, getAttributeClassForDatabaseType(nestedDbType)); |
| } |
| } |
| } |
| |
| /** |
| * Build descriptor and mappings for a VArray argument. The newly |
| * created descriptor will be added to the given OX project. |
| */ |
| protected void addToORProjectForVArrayArg(DatabaseType dbType, Project orProject, String arrayName, String arrayAlias) { |
| DatabaseType nestedDbType = ((VArrayType)dbType).getEnclosedType(); |
| String referenceTypeAlias = getGeneratedAlias(nestedDbType.getTypeName()); |
| String referenceTypeName = getGeneratedJavaClassName(referenceTypeAlias, dbwsBuilder.getProjectName()); |
| ObjectRelationalDataTypeDescriptor ordt = (ObjectRelationalDataTypeDescriptor)orProject.getDescriptorForAlias(arrayAlias); |
| if (ordt == null) { |
| ordt = buildAndAddNewObjectRelationalDataTypeDescriptor(orProject, arrayAlias, arrayName + COLLECTION_WRAPPER_SUFFIX); |
| // before we add this descriptor, check if the nested type's descriptor |
| // should be built and added first |
| ClassDescriptor refdesc = orProject.getDescriptorForAlias(referenceTypeAlias); |
| if (refdesc == null) { |
| if (nestedDbType.isObjectType()) { |
| addToORProjectForObjectTypeArg(nestedDbType, orProject, referenceTypeName, referenceTypeAlias); |
| } |
| } |
| } |
| boolean itemsMappingFound = ordt.getMappingForAttributeName(ITEMS_MAPPING_ATTRIBUTE_NAME) == null ? false : true; |
| if (!itemsMappingFound) { |
| if (nestedDbType.isComposite()) { |
| buildAndAddObjectArrayMapping(ordt, ITEMS_MAPPING_ATTRIBUTE_NAME, ITEMS_MAPPING_FIELD_NAME, referenceTypeName, arrayName); |
| } else { |
| buildAndAddArrayMapping(ordt, ITEMS_MAPPING_ATTRIBUTE_NAME, ITEMS_MAPPING_FIELD_NAME, arrayAlias.toUpperCase(), nestedDbType.getTypeName()); |
| } |
| } |
| } |
| |
| /** |
| * Build descriptor and mappings for an Object type argument. The |
| * newly created descriptor will be added to the given OX project. |
| */ |
| protected void addToOXProjectForObjectTypeArg(DatabaseType dbType, Project oxProject, String objectName, String objectAlias) { |
| XMLDescriptor xdesc = (XMLDescriptor) oxProject.getDescriptorForAlias(objectAlias); |
| if (xdesc == null) { |
| xdesc = buildAndAddNewXMLDescriptor(oxProject, objectAlias, objectName, nct.generateSchemaAlias(dbType.getTypeName()), buildCustomQName(objectName, dbwsBuilder).getNamespaceURI()); |
| } |
| ObjectType oType = (ObjectType) dbType; |
| for (FieldType field : oType.getFields()) { |
| // custom transformer may exclude some fields |
| if (nct.styleForElement(field.getFieldName()) == ElementStyle.NONE) { |
| continue; |
| } |
| String lFieldName = field.getFieldName().toLowerCase(); |
| if (xdesc.getMappingForAttributeName(lFieldName) == null) { |
| if (field.isComposite()) { |
| String targetTypeName2 = field.getEnclosedType().getTypeName(); |
| String alias = getGeneratedAlias(targetTypeName2); |
| XMLDescriptor xdesc2 = (XMLDescriptor) oxProject.getDescriptorForAlias(alias); |
| boolean buildDescriptor = xdesc2 == null; |
| if (buildDescriptor) { |
| xdesc2 = buildAndAddNewXMLDescriptor(oxProject, alias, nct.generateSchemaAlias(targetTypeName2), buildCustomQName(targetTypeName2, dbwsBuilder).getNamespaceURI()); |
| } |
| // handle ObjectType field |
| if (field.getEnclosedType().isObjectType()) { |
| if (buildDescriptor) { |
| // need to update the java class name on the descriptor to include package (project) name |
| xdesc2.setJavaClassName(getGeneratedJavaClassName(alias, dbwsBuilder.getProjectName())); |
| addToOXProjectForObjectTypeArg(field.getEnclosedType(), oxProject, xdesc2.getJavaClassName(), alias); |
| } |
| buildAndAddXMLCompositeObjectMapping(xdesc, lFieldName, xdesc2.getJavaClassName()); |
| } else if (field.getEnclosedType().isVArrayType()) { |
| // handle VArray field |
| if (buildDescriptor) { |
| // need to update the java class name on the descriptor to include package (project) name |
| xdesc2.setJavaClassName(getGeneratedJavaClassName(alias, dbwsBuilder.getProjectName())); |
| addToOXProjectForVArrayArg(field.getEnclosedType(), oxProject, xdesc2.getJavaClassName(), alias); |
| } |
| buildAndAddXMLCompositeDirectCollectionMapping(xdesc, lFieldName, lFieldName + SLASH + TEXT, getAttributeClassForDatabaseType(field.getEnclosedType())); |
| } else if (field.getEnclosedType().isObjectTableType()) { |
| // handle ObjectTableType field |
| if (buildDescriptor) { |
| // need to update the java class name on the descriptor to include package (project) name |
| xdesc2.setJavaClassName(getGeneratedJavaClassName(alias, dbwsBuilder.getProjectName())); |
| // make sure the descriptor is built for the enclosed ObjectType |
| addToOXProjectForObjectTableTypeArg(field.getEnclosedType(), oxProject, targetTypeName2, alias); |
| } |
| ObjectTableType tableType = (ObjectTableType) field.getEnclosedType(); |
| if (tableType.getEnclosedType().isComposite()) { |
| String nestedTypeAlias = getGeneratedAlias(((ObjectTableType) field.getEnclosedType()).getEnclosedType().getTypeName()); |
| String nestedTypeName = getGeneratedJavaClassName(nestedTypeAlias, dbwsBuilder.getProjectName()); |
| buildAndAddXMLCompositeCollectionMapping(xdesc, lFieldName, lFieldName + SLASH + ITEM_MAPPING_NAME, nestedTypeName); |
| } else { |
| buildAndAddXMLCompositeDirectCollectionMapping(xdesc, lFieldName, lFieldName + SLASH + TEXT, getAttributeClassForDatabaseType(tableType)); |
| } |
| } |
| } else { |
| // direct mapping |
| addDirectMappingForFieldType(xdesc, lFieldName, field); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Build descriptor and mappings for an Object type argument. The |
| * newly created descriptor will be added to the given OX project. |
| */ |
| @SuppressWarnings("rawtypes") |
| protected void addToORProjectForObjectTypeArg(DatabaseType dbType, Project orProject, String objectName, String objectAlias) { |
| ObjectRelationalDataTypeDescriptor ordt = (ObjectRelationalDataTypeDescriptor)orProject.getDescriptorForAlias(objectAlias); |
| if (ordt == null) { |
| ordt = buildAndAddNewObjectRelationalDataTypeDescriptor(orProject, objectAlias, objectName); |
| } |
| ObjectType oType = (ObjectType) dbType; |
| for (FieldType fType : oType.getFields()) { |
| String fieldName = fType.getFieldName(); |
| String lFieldName = fieldName.toLowerCase(); |
| |
| // handle field ordering |
| boolean found = false; |
| Vector orderedFields = ordt.getOrderedFields(); |
| for (Iterator i = orderedFields.iterator(); i.hasNext();) { |
| Object o = i.next(); |
| if (o instanceof DatabaseField) { |
| DatabaseField field = (DatabaseField)o; |
| if (field.getName().equalsIgnoreCase(fieldName)) { |
| found = true; |
| break; |
| } |
| } |
| } |
| if (!found) { |
| ordt.addFieldOrdering(fieldName); |
| } |
| if (ordt.getMappingForAttributeName(lFieldName) == null) { |
| if (fType.isComposite()) { |
| String targetTypeName2 = fType.getEnclosedType().getTypeName(); |
| String alias = getGeneratedAlias(targetTypeName2); |
| ObjectRelationalDataTypeDescriptor ordt2 = (ObjectRelationalDataTypeDescriptor)orProject.getDescriptorForAlias(alias); |
| boolean buildDescriptor = ordt2 == null; |
| if (buildDescriptor) { |
| ordt2 = buildAndAddNewObjectRelationalDataTypeDescriptor(orProject, alias); |
| } |
| // handle ObjectType field |
| if (fType.getEnclosedType().isObjectType()) { |
| if (buildDescriptor) { |
| // need to update the java class name on the descriptor to include package (project) name |
| ordt2.setJavaClassName(getGeneratedJavaClassName(alias, dbwsBuilder.getProjectName())); |
| addToORProjectForObjectTypeArg(fType.getEnclosedType(), orProject, ordt2.getJavaClassName(), alias); |
| } |
| buildAndAddStructureMapping(ordt, lFieldName, fieldName, ordt2.getJavaClassName()); |
| } else if (fType.getEnclosedType().isVArrayType()) { |
| // handle VArray field |
| if (buildDescriptor) { |
| // need to update the java class name on the descriptor to include package (project) name |
| ordt2.setJavaClassName(getGeneratedJavaClassName(alias, dbwsBuilder.getProjectName())); |
| addToORProjectForVArrayArg(fType.getEnclosedType(), orProject, ordt2.getJavaClassName(), alias); |
| } |
| buildAndAddArrayMapping(ordt, lFieldName, fieldName, getStructureNameForField(fType, null)); |
| } else if (fType.getEnclosedType().isObjectTableType()) { |
| if (buildDescriptor) { |
| // need to update the java class name on the descriptor to include package (project) name |
| ordt2.setJavaClassName(getGeneratedJavaClassName(alias, dbwsBuilder.getProjectName())); |
| // make sure the descriptor is built for the enclosed ObjectType |
| addToORProjectForObjectTableTypeArg(fType.getEnclosedType(), orProject, targetTypeName2, alias); |
| } |
| if (((ObjectTableType) fType.getEnclosedType()).getEnclosedType().isComposite()) { |
| ObjectType nestedType = (ObjectType)((ObjectTableType) fType.getEnclosedType()).getEnclosedType(); |
| String nestedTypeAlias = getGeneratedAlias(nestedType.getTypeName()); |
| String nestedTypeName = getGeneratedJavaClassName(nestedTypeAlias, dbwsBuilder.getProjectName()); |
| buildAndAddObjectArrayMapping(ordt, lFieldName, fieldName, nestedTypeName, nestedTypeAlias.toUpperCase()); |
| } else { |
| buildAndAddArrayMapping(ordt, lFieldName, fieldName, alias.toUpperCase()); |
| } |
| } |
| } else { |
| // direct mapping |
| DirectToFieldMapping dfm = new DirectToFieldMapping(); |
| dfm.setFieldName(fieldName); |
| dfm.setAttributeName(lFieldName); |
| dfm.setAttributeClassification(getAttributeClassForDatabaseType(fType.getEnclosedType())); |
| ordt.addMapping(dfm); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Build descriptor and mappings for an OracleTableType argument. The |
| * newly created descriptor will be added to the given OX project. |
| */ |
| protected void addToOXProjectForObjectTableTypeArg(DatabaseType dbType, Project oxProject, String objectTableName, String objectTableAlias) { |
| XMLDescriptor xdesc = (XMLDescriptor) oxProject.getDescriptorForAlias(objectTableAlias); |
| if (xdesc == null) { |
| xdesc = buildAndAddNewXMLDescriptor(oxProject, objectTableAlias, objectTableName + COLLECTION_WRAPPER_SUFFIX, nct.generateSchemaAlias(dbType.getTypeName()), buildCustomQName(objectTableName, dbwsBuilder).getNamespaceURI()); |
| } |
| boolean itemsMappingFound = xdesc.getMappingForAttributeName(ITEMS_MAPPING_ATTRIBUTE_NAME) == null ? false : true; |
| if (!itemsMappingFound) { |
| DatabaseType nType = ((ObjectTableType) dbType).getEnclosedType(); |
| if (nType.isObjectType()) { |
| ObjectType oType = (ObjectType)nType; |
| String nestedTypeAlias = getGeneratedAlias(oType.getTypeName()); |
| String nestedTypeName = getGeneratedJavaClassName(nestedTypeAlias, dbwsBuilder.getProjectName()); |
| addToOXProjectForObjectTypeArg(oType, oxProject, nestedTypeName, nestedTypeAlias); |
| // ObjectType is composite |
| buildAndAddXMLCompositeCollectionMapping(xdesc, nestedTypeName); |
| } else { |
| buildAndAddXMLCompositeDirectCollectionMapping(xdesc, ITEMS_MAPPING_ATTRIBUTE_NAME, ITEM_MAPPING_NAME + SLASH + TEXT, getAttributeClassForDatabaseType(nType)); |
| } |
| } |
| } |
| |
| /** |
| * Build descriptor and mappings for an OracleTableType argument. The |
| * newly created descriptor will be added to the given OR project. |
| */ |
| protected void addToORProjectForObjectTableTypeArg(DatabaseType dbType, Project orProject, String objectTableName, String objectTableAlias) { |
| ObjectRelationalDataTypeDescriptor ordt = (ObjectRelationalDataTypeDescriptor)orProject.getDescriptorForAlias(objectTableAlias); |
| if (ordt == null) { |
| ordt = buildAndAddNewObjectRelationalDataTypeDescriptor(orProject, objectTableAlias, objectTableName + COLLECTION_WRAPPER_SUFFIX); |
| } |
| boolean itemsMappingFound = ordt.getMappingForAttributeName(ITEMS_MAPPING_ATTRIBUTE_NAME) == null ? false : true; |
| if (!itemsMappingFound) { |
| DatabaseType nestedType = ((ObjectTableType) dbType).getEnclosedType(); |
| if (nestedType.isObjectType()) { |
| ObjectType oType = (ObjectType) nestedType; |
| String nestedTypeAlias = getGeneratedAlias(oType.getTypeName()); |
| String nestedTypeName = getGeneratedJavaClassName(nestedTypeAlias, dbwsBuilder.getProjectName()); |
| addToORProjectForObjectTypeArg(oType, orProject, nestedTypeName, nestedTypeAlias); |
| // ObjectType is composite |
| buildAndAddObjectArrayMapping(ordt, ITEMS_MAPPING_ATTRIBUTE_NAME, ITEMS_MAPPING_FIELD_NAME, nestedTypeName, nestedTypeAlias.toUpperCase()); |
| } else { |
| buildAndAddArrayMapping(ordt, ITEMS_MAPPING_ATTRIBUTE_NAME, ITEMS_MAPPING_FIELD_NAME, objectTableAlias.toUpperCase()); |
| } |
| } |
| } |
| |
| /** |
| * Build a Query for the given ProcedureType instance and add |
| * it to the given OR project's list of queries. |
| */ |
| @Override |
| @SuppressWarnings({ "rawtypes", "unchecked" }) |
| protected void buildQueryForProcedureType(ProcedureType procType, Project orProject, Project oxProject, ProcedureOperationModel opModel, boolean hasPLSQLArgs) { |
| // if there are one or more PL/SQL args, then we need a PLSQLStoredProcedureCall |
| StoredProcedureCall call; |
| ArgumentType returnArg = procType.isFunctionType() ? ((FunctionType)procType).getReturnArgument() : null; |
| |
| // check for PL/SQL cursor arg |
| boolean hasCursor = hasPLSQLCursorArg(getArgumentListForProcedureType(procType)); |
| hasPLSQLArgs = hasPLSQLArgs || hasCursor || opModel.isPLSQLProcedureOperation(); |
| |
| if (hasPLSQLArgs) { |
| if (procType.isFunctionType()) { |
| org.eclipse.persistence.internal.helper.DatabaseType dType = buildDatabaseTypeFromMetadataType(returnArg, procType.getCatalogName()); |
| if (hasCursor) { |
| call = new PLSQLStoredFunctionCall(); |
| // constructor by default adds a RETURN argument, so remove it |
| ((PLSQLStoredFunctionCall)call).getArguments().remove(0); |
| ((PLSQLStoredFunctionCall)call).useNamedCursorOutputAsResultSet(CURSOR_STR, dType); |
| } else { |
| Class wrapperClass = getWrapperClass(dType); |
| if (wrapperClass != null) { |
| ((ComplexDatabaseType) dType).setJavaType(wrapperClass); |
| } |
| call = new PLSQLStoredFunctionCall(dType); |
| // check for non-associative collection |
| if (returnArg.getEnclosedType().isPLSQLCollectionType() && !((PLSQLCollectionType)returnArg.getEnclosedType()).isIndexed()) { |
| PLSQLargument plsqlArg = ((PLSQLStoredFunctionCall)call).getArguments().get(0); |
| ((PLSQLCollection) plsqlArg.databaseType).setIsNestedTable(true); |
| } |
| } |
| } else { |
| call = new PLSQLStoredProcedureCall(); |
| } |
| } else { |
| if (procType.isFunctionType()) { |
| String javaTypeName = returnArg.getTypeName(); |
| ClassDescriptor desc = oxProject.getDescriptorForAlias(getGeneratedAlias(javaTypeName)); |
| if (desc != null) { |
| javaTypeName = desc.getJavaClassName(); |
| } |
| |
| if (returnArg.isComposite()) { |
| DatabaseType dataType = returnArg.getEnclosedType(); |
| if (dataType.isVArrayType() || dataType.isObjectTableType()) { |
| call = new StoredFunctionCall(Types.ARRAY, returnArg.getTypeName(), javaTypeName, buildFieldForNestedType(dataType)); |
| } else { |
| // assumes ObjectType |
| call = new StoredFunctionCall(Types.STRUCT, returnArg.getTypeName(), javaTypeName); |
| } |
| } else { |
| // scalar |
| call = new StoredFunctionCall(); |
| if (returnArg.getEnclosedType().isBlobType()) { |
| // handle BLOBs |
| ((StoredFunctionCall) call).setResult(null, ClassConstants.BLOB); |
| } else { |
| int resultType = Util.getJDBCTypeFromTypeName(javaTypeName); |
| // need special handling for Date types |
| if (resultType == Types.DATE || resultType == Types.TIME || resultType == Types.TIMESTAMP) { |
| ((StoredFunctionCall) call).setResult(null, ClassConstants.TIMESTAMP); |
| } else if (returnArg.getEnclosedType() == ScalarDatabaseTypeEnum.XMLTYPE_TYPE) { |
| // special handling for XMLType types |
| ((StoredFunctionCall) call).setResult(getJDBCTypeForTypeName(XMLTYPE_STR), XMLTYPE_STR, ClassConstants.OBJECT); |
| } else if (resultType == Types.OTHER || resultType == Types.CLOB) { |
| // default to OBJECT for OTHER, CLOB and LONG types |
| ((StoredFunctionCall) call).setResult(null, ClassConstants.OBJECT); |
| } else { |
| ((StoredFunctionCall) call).setResult(null, resultType); |
| } |
| } |
| } |
| } else { |
| call = new StoredProcedureCall(); |
| } |
| } |
| |
| String cat = procType.getCatalogName(); |
| String catalogPrefix = (cat == null || cat.length() == 0) ? EMPTY_STRING : cat + DOT; |
| call.setProcedureName(catalogPrefix + procType.getProcedureName()); |
| String returnType = opModel.getReturnType(); |
| boolean hasResponse = returnType != null; |
| |
| DatabaseQuery dq = null; |
| if (hasCursor || (hasResponse && opModel.isCollection())) { |
| dq = new DataReadQuery(); |
| } else { |
| dq = new ValueReadQuery(); |
| } |
| dq.bindAllParameters(); |
| dq.setName(getNameForQueryOperation(opModel, procType)); |
| dq.setCall(call); |
| |
| for (ArgumentType arg : procType.getArguments()) { |
| // handle optional arg |
| if (arg.optional()) { |
| call.addOptionalArgument(arg.getArgumentName()); |
| } |
| |
| DatabaseType argType = arg.getEnclosedType(); |
| ArgumentTypeDirection direction = arg.getDirection(); |
| |
| // for PL/SQL |
| org.eclipse.persistence.internal.helper.DatabaseType databaseType = null; |
| // for Advanced JDBC |
| String javaTypeName = null; |
| |
| if (hasPLSQLArgs) { |
| databaseType = buildDatabaseTypeFromMetadataType(argType, cat); |
| } else { |
| javaTypeName = argType.getTypeName(); |
| ClassDescriptor desc = oxProject.getDescriptorForAlias(getGeneratedAlias(javaTypeName)); |
| if (desc != null) { |
| // anything there's a descriptor for will include "packagename." in the class name |
| javaTypeName = desc.getJavaClassName(); |
| } |
| } |
| |
| if (direction == IN) { |
| if (hasPLSQLArgs) { |
| Class wrapperClass = getWrapperClass(databaseType); |
| if (wrapperClass != null) { |
| ((ComplexDatabaseType) databaseType).setJavaType(wrapperClass); |
| } |
| ((PLSQLStoredProcedureCall)call).addNamedArgument(arg.getArgumentName(), databaseType); |
| // check for non-associative collection |
| if (argType.isPLSQLCollectionType() && !((PLSQLCollectionType)argType).isIndexed()) { |
| PLSQLargument plsqlArg = ((PLSQLStoredProcedureCall)call).getArguments().get(((PLSQLStoredProcedureCall)call).getArguments().size()-1); |
| ((PLSQLCollection) plsqlArg.databaseType).setIsNestedTable(true); |
| } |
| } else { |
| if (argType.isVArrayType()) { |
| dq.addArgument(arg.getArgumentName()); |
| call.addNamedArgument(arg.getArgumentName(), arg.getArgumentName(), Types.ARRAY, argType.getTypeName(), javaTypeName); |
| } else if (argType.isObjectType()) { |
| dq.addArgument(arg.getArgumentName()); |
| call.addNamedArgument(arg.getArgumentName(), arg.getArgumentName(), Types.STRUCT, argType.getTypeName(), javaTypeName); |
| } else if (argType.isObjectTableType()) { |
| dq.addArgument(arg.getArgumentName(), java.sql.Array.class); |
| call.addNamedArgument(arg.getArgumentName(), arg.getArgumentName(), Types.ARRAY, argType.getTypeName(), getWrapperClass(javaTypeName), buildFieldForNestedType(argType)); |
| } else { |
| dq.addArgument(arg.getArgumentName()); |
| call.addNamedArgument(arg.getArgumentName(), arg.getArgumentName(), Util.getJDBCTypeFromTypeName(argType.getTypeName())); |
| } |
| } |
| } else if (direction == OUT) { |
| if (hasPLSQLArgs) { |
| if (arg.isPLSQLCursorType()) { |
| ((PLSQLStoredProcedureCall)call).useNamedCursorOutputAsResultSet(arg.getArgumentName(), databaseType); |
| } else { |
| Class wrapperClass = getWrapperClass(databaseType); |
| if (wrapperClass != null) { |
| ((ComplexDatabaseType) databaseType).setJavaType(wrapperClass); |
| } |
| ((PLSQLStoredProcedureCall)call).addNamedOutputArgument(arg.getArgumentName(), databaseType); |
| } |
| } else { |
| if (argType.isComposite()) { |
| Class wrapperClass = getWrapperClass(javaTypeName); |
| |
| if (argType.isVArrayType() || argType.isObjectTableType()) { |
| call.addNamedOutputArgument(arg.getArgumentName(), arg.getArgumentName(), Types.ARRAY, argType.getTypeName(), wrapperClass, buildFieldForNestedType(argType)); |
| } else { |
| // assumes ObjectType |
| call.addNamedOutputArgument(arg.getArgumentName(), arg.getArgumentName(), Types.STRUCT, argType.getTypeName(), wrapperClass); |
| } |
| } else { |
| // need special handling for XMLType - we want the type code to be 'OPAQUE' (2007) |
| if (argType == ScalarDatabaseTypeEnum.XMLTYPE_TYPE) { |
| call.addNamedOutputArgument(arg.getArgumentName(), arg.getArgumentName(), getJDBCTypeForTypeName(XMLTYPE_STR), XMLTYPE_STR); |
| } else if (argType == ScalarDatabaseTypeEnum.SYS_REFCURSOR_TYPE) { |
| call.addNamedCursorOutputArgument(arg.getArgumentName()); |
| } else { |
| call.addNamedOutputArgument(arg.getArgumentName(), arg.getArgumentName(), Util.getJDBCTypeFromTypeName(argType.getTypeName())); |
| } |
| } |
| } |
| } else { // INOUT |
| if (hasPLSQLArgs) { |
| Class wrapperClass = getWrapperClass(databaseType); |
| if (wrapperClass != null) { |
| ((ComplexDatabaseType) databaseType).setJavaType(wrapperClass); |
| } |
| ((PLSQLStoredProcedureCall)call).addNamedInOutputArgument(arg.getArgumentName(), databaseType); |
| // check for non-associative collection |
| if (argType.isPLSQLCollectionType() && !((PLSQLCollectionType)argType).isIndexed()) { |
| PLSQLargument plsqlArg = ((PLSQLStoredProcedureCall)call).getArguments().get(((PLSQLStoredProcedureCall)call).getArguments().size()-1); |
| ((PLSQLCollection) plsqlArg.databaseType).setIsNestedTable(true); |
| } |
| } else { |
| dq.addArgument(arg.getArgumentName()); |
| if (argType.isComposite()) { |
| Class wrapperClass = getWrapperClass(javaTypeName); |
| |
| if (argType.isVArrayType() || argType.isObjectTableType()) { |
| call.addNamedInOutputArgument(arg.getArgumentName(), arg.getArgumentName(), arg.getArgumentName(), Types.ARRAY, argType.getTypeName(), wrapperClass, buildFieldForNestedType(argType)); |
| } else { |
| // assumes ObjectType |
| call.addNamedInOutputArgument(arg.getArgumentName(), arg.getArgumentName(), arg.getArgumentName(), Types.STRUCT, argType.getTypeName()); |
| } |
| } else { |
| // for some reason setting "java.lang.String" as the java type causes problems at runtime |
| Class javaType = getClassFromJDBCType(argType.getTypeName(), dbwsBuilder.getDatabasePlatform()); |
| if (shouldSetJavaType(javaType.getName())) { |
| call.addNamedInOutputArgument(arg.getArgumentName(), arg.getArgumentName(), arg.getArgumentName(), Util.getJDBCTypeFromTypeName(argType.getTypeName()), argType.getTypeName(), javaType); |
| } else { |
| call.addNamedInOutputArgument(arg.getArgumentName()); |
| } |
| } |
| } |
| } |
| if (hasPLSQLArgs && (direction == IN || direction == INOUT)) { |
| ClassDescriptor xdesc = null; |
| if (hasResponse) { |
| int idx = returnType.indexOf(COLON); |
| if (idx == -1) { |
| idx = returnType.indexOf(CLOSE_PAREN); |
| } |
| if (idx > 0) { |
| String typ = returnType.substring(idx+1); |
| for (XMLDescriptor xd : (List<XMLDescriptor>)(List)oxProject.getOrderedDescriptors()) { |
| if (xd.getSchemaReference() != null) { |
| String context = xd.getSchemaReference().getSchemaContext(); |
| if (context.substring(1).equals(typ)) { |
| xdesc = xd; |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| if (xdesc != null) { |
| dq.addArgumentByTypeName(arg.getArgumentName(), xdesc.getJavaClassName()); |
| } else { |
| if (databaseType instanceof PLSQLCollection || databaseType instanceof VArrayType) { |
| dq.addArgument(arg.getArgumentName(), Array.class); |
| } else if (databaseType instanceof PLSQLrecord || databaseType instanceof OracleObjectType) { |
| dq.addArgument(arg.getArgumentName(), Struct.class); |
| } else { |
| dq.addArgument(arg.getArgumentName(), JDBCTypes.getClassForCode(databaseType.getConversionCode())); |
| } |
| } |
| } |
| } |
| orProject.getQueries().add(dq); |
| } |
| |
| /** |
| * Build an OR database field for a given type's nested type. |
| */ |
| protected ObjectRelationalDatabaseField buildFieldForNestedType(DatabaseType owningType) { |
| ObjectRelationalDatabaseField nestedField = new ObjectRelationalDatabaseField(""); |
| DatabaseType nestedType; |
| if (owningType.isVArrayType()) { |
| nestedType = ((VArrayType)owningType).getEnclosedType(); |
| if (nestedType.isComposite()) { |
| nestedField.setSqlTypeName(nestedType.getTypeName()); |
| nestedField.setSqlType(Types.STRUCT); |
| } else { |
| nestedField.setSqlTypeName(Util.getJDBCTypeNameFromType(Types.ARRAY)); |
| nestedField.setSqlType(Types.ARRAY); |
| } |
| } else { |
| nestedType = ((ObjectTableType)owningType).getEnclosedType(); |
| nestedField.setSqlTypeName(nestedType.getTypeName()); |
| nestedField.setSqlType(Types.STRUCT); |
| } |
| nestedField.setTypeName(getGeneratedJavaClassName(nestedType.getTypeName().toLowerCase(), dbwsBuilder.getProjectName())); |
| return nestedField; |
| } |
| |
| /** |
| * Create an XMLDirectMapping for a given FieldType instance, and add the |
| * newly created mapping to the given XMLDescriptor. |
| */ |
| protected void addDirectMappingForFieldType(XMLDescriptor xdesc, String attributeName, FieldType fType) { |
| XMLDirectMapping fieldMapping = new XMLDirectMapping(); |
| fieldMapping.setAttributeName(attributeName); |
| |
| XMLField xField; |
| if (nct.styleForElement(attributeName) == ElementStyle.ATTRIBUTE) { |
| xField = new XMLField(AT_SIGN + attributeName); |
| } else { |
| xField = new XMLField(attributeName + SLASH + TEXT); |
| } |
| |
| QName qnameFromDatabaseType = getXMLTypeFromJDBCType(org.eclipse.persistence.tools.dbws.Util.getJDBCTypeFromTypeName(fType.getTypeName())); |
| xField.setSchemaType(qnameFromDatabaseType); |
| // special case to avoid Calendar problems |
| if (qnameFromDatabaseType == DATE_QNAME) { |
| fieldMapping.setAttributeClassification(java.sql.Date.class); |
| xField.addXMLConversion(DATE_QNAME, java.sql.Date.class); |
| xField.addJavaConversion(java.sql.Date.class, DATE_QNAME); |
| xdesc.getNamespaceResolver().put(SCHEMA_PREFIX, SCHEMA_URL); |
| } else { |
| Class<?> attributeClass = XMLConversionManager.getDefaultXMLTypes().get(qnameFromDatabaseType); |
| if (attributeClass == null) { |
| attributeClass = CoreClassConstants.OBJECT; |
| } |
| fieldMapping.setAttributeClassification(attributeClass); |
| } |
| fieldMapping.setField(xField); |
| AbstractNullPolicy nullPolicy = fieldMapping.getNullPolicy(); |
| nullPolicy.setNullRepresentedByEmptyNode(false); |
| nullPolicy.setMarshalNullRepresentation(XSI_NIL); |
| nullPolicy.setNullRepresentedByXsiNil(true); |
| fieldMapping.setNullPolicy(nullPolicy); |
| xdesc.getNamespaceResolver().put(SCHEMA_INSTANCE_PREFIX, SCHEMA_INSTANCE_URL); // to support xsi:nil policy |
| xdesc.addMapping(fieldMapping); |
| } |
| |
| /** |
| * Build an XMLCompositeObjectMapping based on given attribute and reference |
| * class names, and add the newly created mapping to the given descriptor. |
| */ |
| protected void buildAndAddXMLCompositeObjectMapping(XMLDescriptor xdesc, String attributeName, String referenceClassName) { |
| xdesc.addMapping(buildXMLCompositeObjectMapping(attributeName, referenceClassName)); |
| } |
| /** |
| * Build an XMLCompositeObjectMapping based on given attribute and reference |
| * class names, and add the newly created mapping to the given descriptor. |
| */ |
| protected void buildAndAddXMLCompositeObjectMapping(XMLDescriptor xdesc, String attributeName, String xpath, String referenceClassName) { |
| xdesc.addMapping(buildXMLCompositeObjectMapping(attributeName, referenceClassName)); |
| } |
| /** |
| * Build an XMLCompositeObjectMapping based on given attribute |
| * and reference class names. |
| */ |
| protected XMLCompositeObjectMapping buildXMLCompositeObjectMapping(String attributeName, String referenceClassName) { |
| return buildXMLCompositeObjectMapping(attributeName, attributeName, referenceClassName); |
| } |
| /** |
| * Build an XMLCompositeObjectMapping based on given attribute |
| * and reference class names. |
| */ |
| protected XMLCompositeObjectMapping buildXMLCompositeObjectMapping(String attributeName, String xpath, String referenceClassName) { |
| XMLCompositeObjectMapping mapping = new XMLCompositeObjectMapping(); |
| mapping.setAttributeName(attributeName); |
| mapping.setXPath(xpath); |
| XMLField xField = (XMLField)mapping.getField(); |
| xField.setRequired(true); |
| mapping.setReferenceClassName(referenceClassName); |
| return mapping; |
| } |
| |
| /** |
| * Build an XMLCompositeCollectionMapping based on a given attribute name, xpath, |
| * and reference class, and add the newly created mapping to the given descriptor. |
| */ |
| protected void buildAndAddXMLCompositeCollectionMapping(XMLDescriptor xdesc, String attributeName, String xPath, String referenceClassName) { |
| xdesc.addMapping(buildXMLCompositeCollectionMapping(attributeName, xPath, referenceClassName)); |
| } |
| /** |
| * Build an XMLCompositeCollectionMapping based on a given reference class |
| * name, and add the newly created mapping to the given descriptor. |
| */ |
| protected void buildAndAddXMLCompositeCollectionMapping(XMLDescriptor xdesc, String referenceClassName) { |
| xdesc.addMapping(buildXMLCompositeCollectionMapping(referenceClassName)); |
| } |
| /** |
| * Build an XMLCompositeCollectionMapping based on a given reference class name. |
| * The attribute name will be set to 'items', and the xpath set to 'item'. |
| */ |
| protected XMLCompositeCollectionMapping buildXMLCompositeCollectionMapping(String referenceClassName) { |
| return buildXMLCompositeCollectionMapping(ITEMS_MAPPING_ATTRIBUTE_NAME, ITEM_MAPPING_NAME, referenceClassName); |
| } |
| /** |
| * Build an XMLCompositeCollectionMapping based on a given attribute name, xpath, |
| * and reference class. |
| */ |
| protected XMLCompositeCollectionMapping buildXMLCompositeCollectionMapping(String attributeName, String xPath, String referenceClassName) { |
| XMLCompositeCollectionMapping itemsMapping = new XMLCompositeCollectionMapping(); |
| itemsMapping.setAttributeName(attributeName); |
| itemsMapping.setXPath(xPath); |
| ((XMLField)itemsMapping.getField()).setRequired(true); |
| itemsMapping.useCollectionClass(ArrayList.class); |
| itemsMapping.setReferenceClassName(referenceClassName); |
| return itemsMapping; |
| } |
| |
| /** |
| * Build an XMLCompositeDirectCollectionMapping based on a given attribute name, xpath, |
| * and attribute element class. The newly created mapping will be added to the given |
| * XML descriptor. |
| */ |
| protected XMLCompositeDirectCollectionMapping buildAndAddXMLCompositeDirectCollectionMapping(XMLDescriptor xdesc, String attributeName, String xPath, Class<?> attributeElementClass) { |
| XMLCompositeDirectCollectionMapping itemsMapping = buildXMLCompositeDirectCollectionMapping(attributeName, xPath, attributeElementClass); |
| xdesc.getNamespaceResolver().put(SCHEMA_INSTANCE_PREFIX, SCHEMA_INSTANCE_URL); // to support xsi:nil policy |
| xdesc.addMapping(itemsMapping); |
| return itemsMapping; |
| } |
| /** |
| * Build an XMLCompositeDirectCollectionMapping based on a given attribute name, xpath, |
| * and attribute element class. |
| */ |
| protected XMLCompositeDirectCollectionMapping buildXMLCompositeDirectCollectionMapping(String attributeName, String xPath, Class<?> attributeElementClass) { |
| XMLCompositeDirectCollectionMapping itemsMapping = new XMLCompositeDirectCollectionMapping(); |
| itemsMapping.setAttributeElementClass(attributeElementClass); |
| itemsMapping.setAttributeName(attributeName); |
| itemsMapping.setUsesSingleNode(true); |
| itemsMapping.setXPath(xPath); |
| ((XMLField)itemsMapping.getField()).setRequired(true); |
| itemsMapping.useCollectionClass(ArrayList.class); |
| AbstractNullPolicy nullPolicy = itemsMapping.getNullPolicy(); |
| nullPolicy.setNullRepresentedByEmptyNode(false); |
| nullPolicy.setMarshalNullRepresentation(XSI_NIL); |
| nullPolicy.setNullRepresentedByXsiNil(true); |
| itemsMapping.setNullPolicy(nullPolicy); |
| return itemsMapping; |
| } |
| |
| /** |
| * Builds a StructureMapping based on a given attributeName, fieldName and reference |
| * class name, and adds the newly created mapping to the given OR descriptor. |
| */ |
| protected StructureMapping buildAndAddStructureMapping(ObjectRelationalDataTypeDescriptor orDesc, String attributeName, String fieldName, String referenceClassName) { |
| StructureMapping structureMapping = buildStructureMapping(attributeName, fieldName, referenceClassName); |
| orDesc.addMapping(structureMapping); |
| return structureMapping; |
| } |
| /** |
| * Builds a StructureMapping based on a given attributeName, fieldName |
| * and reference class name. |
| */ |
| protected StructureMapping buildStructureMapping(String attributeName, String fieldName, String referenceClassName) { |
| StructureMapping structureMapping = new StructureMapping(); |
| structureMapping.setAttributeName(attributeName); |
| structureMapping.setFieldName(fieldName); |
| structureMapping.setReferenceClassName(referenceClassName); |
| // we have a map of created descriptors, keyed on javaClassName, which - along with a |
| // list of referenceClassNames (set upon reference mapping creation) will allow us |
| // to set aggregate descriptors as required. |
| referencedORDescriptors.add(referenceClassName); |
| |
| return structureMapping; |
| } |
| |
| /** |
| * Builds an ObjectArrayMapping based on a given attribute name, field name, |
| * reference class name, field type and package name, and adds the newly |
| * created mapping to the given OR descriptor. |
| */ |
| protected ObjectArrayMapping buildAndAddObjectArrayMapping(ObjectRelationalDataTypeDescriptor orDesc, String attributeName, String fieldName, String referenceClassName, String structureName) { |
| ObjectArrayMapping objectArrayMapping = buildObjectArrayMapping(attributeName, fieldName, referenceClassName, structureName); |
| orDesc.addMapping(objectArrayMapping); |
| return objectArrayMapping; |
| } |
| /** |
| * Builds an ObjectArrayMapping based on a given attribute name, field name, |
| * reference class name and structureName. |
| */ |
| protected ObjectArrayMapping buildObjectArrayMapping(String attributeName, String fieldName, String referenceClassName, String structureName) { |
| ObjectArrayMapping objectArrayMapping = new ObjectArrayMapping(); |
| objectArrayMapping.setAttributeName(attributeName); |
| objectArrayMapping.setFieldName(fieldName); |
| objectArrayMapping.setStructureName(structureName); |
| objectArrayMapping.useCollectionClass(ArrayList.class); |
| objectArrayMapping.setReferenceClassName(referenceClassName); |
| // we have a map of created descriptors, keyed on javaClassName, which - along with a |
| // list of referenceClassNames (set upon reference mapping creation) will allow us |
| // to set aggregate descriptors as required. |
| referencedORDescriptors.add(referenceClassName); |
| |
| return objectArrayMapping; |
| } |
| |
| /** |
| * Build an ArrayMapping based on a given attribute name, field name, structure name and |
| * nested type name. The newly created mapping will be added to the given OR descriptor. |
| */ |
| protected ArrayMapping buildAndAddArrayMapping(ObjectRelationalDataTypeDescriptor orDesc, String attributeName, String fieldName, String structureName, String nestedTypeName) { |
| ArrayMapping arrayMapping = buildArrayMapping(attributeName, fieldName, structureName); |
| arrayMapping.setElementDataTypeName(nestedTypeName); |
| orDesc.addMapping(arrayMapping); |
| return arrayMapping; |
| } |
| /** |
| * Build an ArrayMapping based on a given attribute name, field name and structure |
| * name. The newly created mapping will be added to the given OR descriptor. |
| */ |
| protected ArrayMapping buildAndAddArrayMapping(ObjectRelationalDataTypeDescriptor orDesc, String attributeName, String fieldName, String structureName) { |
| ArrayMapping arrayMapping = buildArrayMapping(attributeName, fieldName, structureName); |
| orDesc.addMapping(arrayMapping); |
| return arrayMapping; |
| } |
| /** |
| * Build an ArrayMapping based on a given attribute name, field name and structure |
| * name. |
| */ |
| protected ArrayMapping buildArrayMapping(String attributeName, String fieldName, String structureName) { |
| ArrayMapping arrayMapping = new ArrayMapping(); |
| arrayMapping.setAttributeName(attributeName); |
| arrayMapping.setFieldName(fieldName); |
| arrayMapping.setStructureName(structureName); |
| arrayMapping.useCollectionClass(ArrayList.class); |
| return arrayMapping; |
| } |
| |
| /** |
| * Build an XMLDescriptor based on a given descriptor alias, schema alias and target |
| * namespace, and add the newly created descriptor to the given OX Project. |
| */ |
| protected XMLDescriptor buildAndAddNewXMLDescriptor(Project oxProject, String objectAlias, String userType, String targetNamespace) { |
| return buildAndAddNewXMLDescriptor(oxProject, objectAlias, objectAlias, userType, targetNamespace); |
| } |
| /** |
| * Build an XMLDescriptor based on a given descriptor alias, schema alias, java class name |
| * and target namespace, and add the newly created descriptor to the given OX Project. |
| */ |
| protected XMLDescriptor buildAndAddNewXMLDescriptor(Project oxProject, String objectAlias, String javaClassName, String userType, String targetNamespace) { |
| XMLDescriptor xdesc = buildNewXMLDescriptor(objectAlias, javaClassName, userType, targetNamespace); |
| oxProject.addDescriptor(xdesc); |
| return xdesc; |
| } |
| /** |
| * Build an XMLDescriptor based on a given descriptor alias, |
| * schema alias, and target namespace. |
| */ |
| protected XMLDescriptor buildNewXMLDescriptor(String objectAlias, String userType, String targetNamespace) { |
| return buildNewXMLDescriptor(objectAlias, objectAlias, userType, targetNamespace); |
| } |
| /** |
| * Build an XMLDescriptor based on a given descriptor alias, |
| * java class name schema alias, and target namespace. |
| */ |
| protected XMLDescriptor buildNewXMLDescriptor(String objectAlias, String javaClassName, String userType, String targetNamespace) { |
| XMLDescriptor xdesc = new XMLDescriptor(); |
| xdesc.setAlias(objectAlias); |
| xdesc.setJavaClassName(javaClassName); |
| xdesc.getQueryManager(); |
| XMLSchemaURLReference schemaReference = new XMLSchemaURLReference(); |
| schemaReference.setSchemaContext(SLASH + userType); |
| schemaReference.setType(org.eclipse.persistence.platform.xml.XMLSchemaReference.COMPLEX_TYPE); |
| xdesc.setSchemaReference(schemaReference); |
| NamespaceResolver nr = new NamespaceResolver(); |
| nr.setDefaultNamespaceURI(targetNamespace); |
| xdesc.setNamespaceResolver(nr); |
| xdesc.setDefaultRootElement(userType); |
| return xdesc; |
| } |
| |
| /** |
| * Build an ObjectRelationalDataTypeDescriptor based on a given |
| * descriptor alias and add it to the given OR Project. |
| */ |
| protected ObjectRelationalDataTypeDescriptor buildAndAddNewObjectRelationalDataTypeDescriptor(Project orProject, String alias) { |
| return buildAndAddNewObjectRelationalDataTypeDescriptor(orProject, alias, alias); |
| } |
| /** |
| * Build an ObjectRelationalDataTypeDescriptor based on a given descriptor |
| * alias and java class name, and add it to the given OR Project. |
| */ |
| protected ObjectRelationalDataTypeDescriptor buildAndAddNewObjectRelationalDataTypeDescriptor(Project orProject, String alias, String javaClassName) { |
| ObjectRelationalDataTypeDescriptor ordesc = buildNewObjectRelationalDataTypeDescriptor(alias, javaClassName); |
| orProject.addDescriptor(ordesc); |
| return ordesc; |
| } |
| /** |
| * Build an ObjectRelationalDataTypeDescriptor based on a given |
| * descriptor alias. |
| */ |
| protected ObjectRelationalDataTypeDescriptor buildNewObjectRelationalDataTypeDescriptor(String alias) { |
| return buildNewObjectRelationalDataTypeDescriptor(alias, alias); |
| } |
| /** |
| * Build an ObjectRelationalDataTypeDescriptor based on a given |
| * descriptor alias and java class name. |
| */ |
| protected ObjectRelationalDataTypeDescriptor buildNewObjectRelationalDataTypeDescriptor(String alias, String javaClassName) { |
| ObjectRelationalDataTypeDescriptor ordt = new ObjectRelationalDataTypeDescriptor(); |
| ordt.setStructureName(alias.toUpperCase()); |
| ordt.descriptorIsAggregate(); |
| |
| // we have a map of created descriptors, keyed on javaClassName, which - along with a |
| // list of referenceClassNames (set upon reference mapping creation) - will allow us |
| // to set aggregate descriptors as required. |
| createdORDescriptors.put(javaClassName, ordt); |
| |
| ordt.setAlias(alias); |
| ordt.setJavaClassName(javaClassName); |
| ordt.getQueryManager(); |
| return ordt; |
| } |
| |
| /** |
| * Return the structure name to be set on a mapping based on a given |
| * FieldType and packageName. |
| */ |
| protected String getStructureNameForField(FieldType fType, String packageName) { |
| DatabaseType type = fType.getEnclosedType(); |
| String structureName = type.getTypeName(); |
| if (packageName != null && packageName.length() > 0 && !packageName.equals(TOPLEVEL)) { |
| structureName = packageName + UNDERSCORE + structureName; |
| } |
| return structureName; |
| } |
| |
| /** |
| * Customizes the simple-xml-format tags names to better represent the |
| * PL/SQL record/table/column type. This is possible only with |
| * strongly-typed ref cursors, since for weakly-typed ones we |
| * don't know anything about the cursor's output type. |
| */ |
| protected void customizeSimpleXMLTagNames(PLSQLCursorType plsqlCursor, ProcedureOperationModel procedureOperationModel) { |
| if (!plsqlCursor.isWeaklyTyped()) { |
| // do not override user tag customization |
| if (procedureOperationModel.getSimpleXMLFormatTag() == null) { |
| procedureOperationModel.setSimpleXMLFormatTag(plsqlCursor.getCursorName()); |
| } |
| |
| // Enclosed type could be one of: |
| // - PLSQLRecordType |
| // - ROWTYPEType |
| // - TYPEType |
| if (procedureOperationModel.getXmlTag() == null) { |
| if (plsqlCursor.getEnclosedType().isPLSQLRecordType()) { |
| PLSQLRecordType recType = (PLSQLRecordType) plsqlCursor.getEnclosedType(); |
| procedureOperationModel.setXmlTag(recType.getTypeName()); |
| } else if (plsqlCursor.getEnclosedType().isROWTYPEType()) { |
| // assumes ROWTYPEType has an enclosed TableType |
| ROWTYPEType rowType = (ROWTYPEType) plsqlCursor.getEnclosedType(); |
| TableType tableType = (TableType) rowType.getEnclosedType(); |
| procedureOperationModel.setXmlTag(tableType.getTableName()); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Overridden for wrapping call with call to {@link #translateToOracleType} method. |
| */ |
| @Override |
| protected org.eclipse.persistence.internal.helper.DatabaseType buildDatabaseTypeFromMetadataType(DatabaseType dType, String catalog) { |
| org.eclipse.persistence.internal.helper.DatabaseType databaseType = super.buildDatabaseTypeFromMetadataType(dType, catalog); |
| return translateToOracleType(databaseType); |
| } |
| |
| /** |
| * Provides the possibility to override generic type with applicable Oracle specific type. |
| * |
| * @param databaseType the generic DatabaseType to override |
| * @return the Oracle specific DatabaseType if such exists |
| */ |
| private org.eclipse.persistence.internal.helper.DatabaseType translateToOracleType(org.eclipse.persistence.internal.helper.DatabaseType databaseType) { |
| switch (databaseType.getTypeName()) { |
| case "NVARCHAR": |
| return JDBCTypes.NVARCHAR2_TYPE; |
| default: |
| return databaseType; |
| } |
| } |
| } |