/******************************************************************************* * Copyright (c) 1998, 2015 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; 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.helper.ClassConstants.Object_Class; 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.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 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 {@see List} of name patterns. * @return {@see 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 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 = (Class<?>)XMLConversionManager.getDefaultXMLTypes().get(qnameFromDatabaseType); if (attributeClass == null) { attributeClass = Object_Class; } 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; } } }