| /* |
| * 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: |
| // David McCann - 2.6.0 - July 09, 2013 - Initial Implementation |
| package org.eclipse.persistence.tools.metadata.generation; |
| |
| import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.EL_ACCESS_VIRTUAL; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.ALL_QUERYNAME; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.AND_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.ARRAYLIST_CLS_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.CLOSE_BRACKET; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.COMMA_SPACE_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.CREATE_OPERATION_NAME; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.CURSOR_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.DELETE_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.DOT; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.EQUALS_BINDING1_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.EQUALS_BINDING_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.INSERT_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.ITEMS_COL_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.ITEMS_FLD_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.OPEN_BRACKET; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.OUT_CURSOR_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.PERCENT; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.PK_QUERYNAME; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.REMOVE_OPERATION_NAME; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.RESULT_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.ROWTYPE_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.SELECT_FROM_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.SET_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.SINGLE_SPACE; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.TYPE_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.UNDERSCORE; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.UPDATE_OPERATION_NAME; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.UPDATE_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.VALUES_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.WHERE_STR; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.getAttributeTypeNameForFieldType; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.getClassNameFromJDBCTypeName; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.getEntityName; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.getGeneratedJavaClassName; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.getJDBCTypeFromTypeName; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.getJDBCTypeName; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.getOraclePLSQLTypeForName; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.getQualifiedCompatibleTypeName; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.getQualifiedTypeName; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.getUnqualifiedEntityName; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.handleOverloading; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.isArgPLSQLScalar; |
| import static org.eclipse.persistence.tools.metadata.generation.Util.processTypeName; |
| |
| import java.security.AccessController; |
| import java.security.PrivilegedActionException; |
| import java.sql.Types; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform; |
| import org.eclipse.persistence.internal.helper.Helper; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.MetadataHelper; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.ClassAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EmbeddableAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.MappedSuperclassAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.XMLAttributes; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.BasicAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.BasicCollectionAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.BasicMapAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ElementCollectionAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.EmbeddedAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.IdAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ManyToManyAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ManyToOneAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.MappingAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.OneToManyAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.OneToOneAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.TransformationAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.TransientAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.VariableOneToOneAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.VersionAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.columns.ColumnMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.columns.TenantDiscriminatorColumnMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.converters.MixedConverterMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.converters.ObjectTypeConverterMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.converters.SerializedConverterMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.converters.StructConverterMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.converters.TypeConverterMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.partitioning.HashPartitioningMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.partitioning.PartitioningMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.partitioning.PinnedPartitioningMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.partitioning.RangePartitioningMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.partitioning.ReplicationPartitioningMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.partitioning.RoundRobinPartitioningMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.partitioning.ValuePartitioningMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.NamedNativeQueryMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.NamedPLSQLStoredFunctionQueryMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.NamedPLSQLStoredProcedureQueryMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.NamedQueryMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.NamedStoredFunctionQueryMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.NamedStoredProcedureQueryMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.OracleArrayTypeMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.OracleObjectTypeMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.PLSQLParameterMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.PLSQLRecordMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.PLSQLTableMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.SQLResultSetMappingMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.queries.StoredProcedureParameterMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.sequencing.SequenceGeneratorMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.sequencing.TableGeneratorMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.structures.ArrayAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.structures.StructMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.structures.StructureAccessor; |
| import org.eclipse.persistence.internal.jpa.metadata.tables.TableMetadata; |
| import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings; |
| import org.eclipse.persistence.internal.security.PrivilegedAccessHelper; |
| import org.eclipse.persistence.internal.security.PrivilegedClassForName; |
| 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.CompositeDatabaseTypeWithEnclosedType; |
| 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.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.TYPEType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.TableType; |
| import org.eclipse.persistence.tools.oracleddl.metadata.VArrayType; |
| |
| /** |
| * This class is responsible for generating an XMLEntityMappings instance based |
| * on a given list of meta-model database types. |
| * |
| * @see org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings |
| * @see org.eclipse.persistence.tools.oracleddl.metadata.CompositeDatabaseType |
| */ |
| public class JPAMetadataGenerator { |
| protected XMLEntityMappings xmlEntityMappings; |
| protected DatabasePlatform dbPlatform; |
| protected String defaultPackage; |
| protected boolean generateCRUDOps = false; |
| |
| // keep track of processed composite types to avoid duplicates and wasted effort |
| protected List<String> processedTypes = null; |
| |
| // keep track of processed embeddables to avoid duplicates and wasted effort |
| protected List<String> generatedEmbeddables = null; |
| |
| // default platform will be Oracle11Platform |
| protected static final String DEFAULT_PLATFORM = "org.eclipse.persistence.platform.database.oracle.Oracle11Platform"; |
| |
| /** |
| * Default constructor. Sets the default package name to null, and dbPlatform to |
| * org.eclipse.persistence.platform.database.oracle.Oracle11Platform. |
| * |
| * The default package name will be prepended to generated class names for database |
| * artifacts that are not in a PL/SQL package. |
| * |
| * The database platform is used to get class names for database types, i.e. |
| * java.math.BigDecimal for DECIMAL. |
| * |
| * @see "org.eclipse.persistence.platform.database.oracle.Oracle11Platform" |
| * @see org.eclipse.persistence.internal.databaseaccess.DatabasePlatform |
| */ |
| public JPAMetadataGenerator() { |
| this(null, DEFAULT_PLATFORM); |
| } |
| |
| /** |
| * This constructor allows setting the default package name and database platform. |
| * |
| * @param defaultPackage package name to be prepended to generated class names for artifacts |
| * not in a PL/SQL package such as an Entity (to avoid having classes in the default package) |
| * @param platformClassName class name of the DatabasePlatform to be used to get class names |
| * for database types, i.e. java.math.BigDecimal for DECIMAL. |
| * @see org.eclipse.persistence.internal.databaseaccess.DatabasePlatform |
| */ |
| public JPAMetadataGenerator(String defaultPackage, String platformClassName) { |
| this(defaultPackage, loadDatabasePlatform(platformClassName)); |
| } |
| |
| /** |
| * This constructor allows setting the default package name and database platform. |
| * |
| * @param defaultPackage package name to be prepended to generated class names for artifacts |
| * not in a PL/SQL package such as an Entity (to avoid having classes in the default package) |
| * @param dbPlatform DatabasePlatform to be used to get class names for database types, i.e. |
| * java.math.BigDecimal for DECIMAL. |
| * @see org.eclipse.persistence.internal.databaseaccess.DatabasePlatform |
| */ |
| public JPAMetadataGenerator(String defaultPackage, DatabasePlatform dbPlatform) { |
| this(defaultPackage, dbPlatform, false); |
| } |
| |
| /** |
| * This constructor allows setting the default package name and database platform. |
| * |
| * @param defaultPackage package name to be prepended to generated class names for artifacts |
| * not in a PL/SQL package such as an Entity (to avoid having classes in the default package) |
| * @param dbPlatform DatabasePlatform to be used to get class names for database types, i.e. |
| * java.math.BigDecimal for DECIMAL. |
| * @param generateCRUDOps if true, CRUD operations (NamedNativeQueryMetadata) will be |
| * generated for each Entity |
| * @see org.eclipse.persistence.internal.databaseaccess.DatabasePlatform |
| */ |
| public JPAMetadataGenerator(String defaultPackage, DatabasePlatform dbPlatform, boolean generateCRUDOps) { |
| this.defaultPackage = defaultPackage == null ? null : defaultPackage.toLowerCase(); |
| this.dbPlatform = dbPlatform; |
| this.generateCRUDOps = generateCRUDOps; |
| |
| xmlEntityMappings = new XMLEntityMappings(); |
| |
| // initialize the various lists - some used, some not |
| initializeXMLEntityMappingLists(); |
| } |
| |
| /** |
| * XMLEntityMappings processing at runtime (i.e. PersistenceUnitProcessor.processORMetadata) |
| * assumes that all lists are initialized. We need to init all lists to avoid runtime |
| * exceptions. |
| * |
| * @see org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings |
| */ |
| protected void initializeXMLEntityMappingLists() { |
| // Entities and Embeddables |
| xmlEntityMappings.setEntities(new ArrayList<EntityAccessor>()); |
| xmlEntityMappings.setEmbeddables(new ArrayList<EmbeddableAccessor>()); |
| |
| // PL/SQL and advanced Oracle types |
| xmlEntityMappings.setPLSQLRecords(new ArrayList<PLSQLRecordMetadata>()); |
| xmlEntityMappings.setPLSQLTables(new ArrayList<PLSQLTableMetadata>()); |
| xmlEntityMappings.setOracleObjectTypes(new ArrayList<OracleObjectTypeMetadata>()); |
| xmlEntityMappings.setOracleArrayTypes(new ArrayList<OracleArrayTypeMetadata>()); |
| |
| // queries |
| xmlEntityMappings.setNamedNativeQueries(new ArrayList<NamedNativeQueryMetadata>()); |
| xmlEntityMappings.setNamedPLSQLStoredFunctionQueries(new ArrayList<NamedPLSQLStoredFunctionQueryMetadata>()); |
| xmlEntityMappings.setNamedPLSQLStoredProcedureQueries(new ArrayList<NamedPLSQLStoredProcedureQueryMetadata>()); |
| xmlEntityMappings.setNamedStoredFunctionQueries(new ArrayList<NamedStoredFunctionQueryMetadata>()); |
| xmlEntityMappings.setNamedStoredProcedureQueries(new ArrayList<NamedStoredProcedureQueryMetadata>()); |
| |
| // initialize other various lists (to avoid exceptions) |
| xmlEntityMappings.setMixedConverters(new ArrayList<MixedConverterMetadata>()); |
| xmlEntityMappings.setMappedSuperclasses(new ArrayList<MappedSuperclassAccessor>()); |
| xmlEntityMappings.setTenantDiscriminatorColumns(new ArrayList<TenantDiscriminatorColumnMetadata>()); |
| xmlEntityMappings.setTypeConverters(new ArrayList<TypeConverterMetadata>()); |
| xmlEntityMappings.setObjectTypeConverters(new ArrayList<ObjectTypeConverterMetadata>()); |
| xmlEntityMappings.setSerializedConverters(new ArrayList<SerializedConverterMetadata>()); |
| xmlEntityMappings.setStructConverters(new ArrayList<StructConverterMetadata>()); |
| xmlEntityMappings.setTableGenerators(new ArrayList<TableGeneratorMetadata>()); |
| xmlEntityMappings.setSequenceGenerators(new ArrayList<SequenceGeneratorMetadata>()); |
| xmlEntityMappings.setPartitioning(new ArrayList<PartitioningMetadata>()); |
| xmlEntityMappings.setReplicationPartitioning(new ArrayList<ReplicationPartitioningMetadata>()); |
| xmlEntityMappings.setRoundRobinPartitioning(new ArrayList<RoundRobinPartitioningMetadata>()); |
| xmlEntityMappings.setPinnedPartitioning(new ArrayList<PinnedPartitioningMetadata>()); |
| xmlEntityMappings.setRangePartitioning(new ArrayList<RangePartitioningMetadata>()); |
| xmlEntityMappings.setValuePartitioning(new ArrayList<ValuePartitioningMetadata>()); |
| xmlEntityMappings.setHashPartitioning(new ArrayList<HashPartitioningMetadata>()); |
| xmlEntityMappings.setNamedQueries(new ArrayList<NamedQueryMetadata>()); |
| xmlEntityMappings.setSqlResultSetMappings(new ArrayList<SQLResultSetMappingMetadata>()); |
| } |
| |
| /** |
| * XMLAttributes processing at runtime (i.e. PersistenceUnitProcessor.processORMetadata) |
| * assumes that all lists are initialized. We need to init all lists to avoid runtime |
| * exceptions. |
| * |
| * @see org.eclipse.persistence.internal.jpa.metadata.accessors.classes.XMLAttributes |
| */ |
| protected void initializeXMLAttributeLists(ClassAccessor accessor) { |
| accessor.setAttributes(new XMLAttributes()); |
| accessor.getAttributes().setIds(new ArrayList<IdAccessor>()); |
| accessor.getAttributes().setBasics(new ArrayList<BasicAccessor>()); |
| accessor.getAttributes().setArrays(new ArrayList<ArrayAccessor>()); |
| accessor.getAttributes().setStructures(new ArrayList<StructureAccessor>()); |
| accessor.getAttributes().setEmbeddeds(new ArrayList<EmbeddedAccessor>()); |
| |
| // initialize other various lists (to avoid exceptions) |
| accessor.getAttributes().setBasicCollections(new ArrayList<BasicCollectionAccessor>()); |
| accessor.getAttributes().setBasicMaps(new ArrayList<BasicMapAccessor>()); |
| accessor.getAttributes().setElementCollections(new ArrayList<ElementCollectionAccessor>()); |
| accessor.getAttributes().setManyToManys(new ArrayList<ManyToManyAccessor>()); |
| accessor.getAttributes().setManyToOnes(new ArrayList<ManyToOneAccessor>()); |
| accessor.getAttributes().setOneToManys(new ArrayList<OneToManyAccessor>()); |
| accessor.getAttributes().setOneToOnes(new ArrayList<OneToOneAccessor>()); |
| accessor.getAttributes().setTransformations(new ArrayList<TransformationAccessor>()); |
| accessor.getAttributes().setTransients(new ArrayList<TransientAccessor>()); |
| accessor.getAttributes().setVariableOneToOnes(new ArrayList<VariableOneToOneAccessor>()); |
| accessor.getAttributes().setVersions(new ArrayList<VersionAccessor>()); |
| } |
| |
| /** |
| * Generate an XMLEntityMappings instance based on a given list of meta-model database types. |
| * |
| * @param databaseTypes the list of meta-model database types to be used to generate an XMLEntityMappings |
| * @see org.eclipse.persistence.tools.oracleddl.metadata.CompositeDatabaseType |
| */ |
| public XMLEntityMappings generateXmlEntityMappings(List<CompositeDatabaseType> databaseTypes) { |
| List<ProcedureType> procedures = new ArrayList<ProcedureType>(); |
| List<TableType> tables = new ArrayList<TableType>(); |
| |
| // populate lists of TableTypes and ProcedureTypes |
| for (CompositeDatabaseType dbType : databaseTypes) { |
| if (dbType.isTableType()) { |
| tables.add((TableType) dbType); |
| } else if (dbType.isProcedureType()) { |
| procedures.add((ProcedureType) dbType); |
| } |
| } |
| |
| // handle stored procedure overloading |
| handleOverloading(procedures); |
| |
| // process TableTypes |
| for (TableType table : tables) { |
| EntityAccessor entity = processTableType(table); |
| xmlEntityMappings.getEntities().add(entity); |
| } |
| // process ProcedureTypes |
| for (ProcedureType procedure : procedures) { |
| // PL/SQL stored procedures and functions will have a PLSQLPackageType as its parent |
| PLSQLPackageType pkgType = procedure.getParentType(); |
| if (pkgType != null) { |
| // handle PL/SQL |
| if (procedure.isFunctionType()) { |
| xmlEntityMappings.getNamedPLSQLStoredFunctionQueries().add(processPLSQLFunctionType((FunctionType) procedure, pkgType)); |
| } else { |
| xmlEntityMappings.getNamedPLSQLStoredProcedureQueries().add(processPLSQLProcedureType(procedure, pkgType)); |
| } |
| } else { |
| // handle top-level (non-PL/SQL) functions and procedures |
| if (procedure.isFunctionType()) { |
| xmlEntityMappings.getNamedStoredFunctionQueries().add(processFunctionType((FunctionType) procedure)); |
| } else { |
| xmlEntityMappings.getNamedStoredProcedureQueries().add(processProcedureType(procedure)); |
| } |
| } |
| } |
| return xmlEntityMappings; |
| } |
| |
| /** |
| * Generate an EntityAccessor based on the given TableType. |
| */ |
| protected EntityAccessor processTableType(TableType tType) { |
| EntityAccessor entity = new EntityAccessor(); |
| entity.setAccess(EL_ACCESS_VIRTUAL); |
| entity.setClassName(getEntityName(tType.getTableName(), defaultPackage)); |
| |
| // initialize the various lists - some used, some not |
| initializeXMLAttributeLists(entity); |
| |
| // set the table name on the entity |
| TableMetadata table = new TableMetadata(); |
| table.setName(tType.getTableName()); |
| entity.setTable(table); |
| |
| // process the table columns |
| for (FieldType fType : tType.getColumns()) { |
| BasicAccessor attribute; |
| // handle primary key |
| if (fType.pk()) { |
| attribute = new IdAccessor(); |
| entity.getAttributes().getIds().add((IdAccessor) attribute); |
| } else { |
| attribute = new BasicAccessor(); |
| entity.getAttributes().getBasics().add(attribute); |
| } |
| attribute.setName(fType.getFieldName().toLowerCase()); |
| attribute.setAttributeType(getAttributeTypeNameForFieldType(fType, dbPlatform)); |
| // set the column name |
| ColumnMetadata column = new ColumnMetadata(); |
| column.setName(fType.getFieldName()); |
| attribute.setColumn(column); |
| } |
| // may need to generated NamedNativeQueryMetadata for CRUD operations |
| generateCRUDMetadata(entity); |
| |
| return entity; |
| } |
| |
| /** |
| * Generate a stored function query based on the given FunctionType. |
| */ |
| protected NamedStoredFunctionQueryMetadata processFunctionType(FunctionType fType) { |
| NamedStoredFunctionQueryMetadata storedFunc = new NamedStoredFunctionQueryMetadata(); |
| storedFunc.setName(getQueryNameForProcedureType(fType)); |
| storedFunc.setProcedureName(fType.getProcedureName()); |
| // set the return parameter |
| storedFunc.setReturnParameter(processArgument(fType.getReturnArgument())); |
| // process the function's arguments |
| if (fType.getArguments().size() > 0) { |
| List<StoredProcedureParameterMetadata> params = new ArrayList<StoredProcedureParameterMetadata>(); |
| for (ArgumentType arg : fType.getArguments()) { |
| params.add(processArgument(arg)); |
| } |
| storedFunc.setParameters(params); |
| } |
| return storedFunc; |
| } |
| |
| /** |
| * Generate a stored procedure query based on the given ProcedureType. |
| */ |
| protected NamedStoredProcedureQueryMetadata processProcedureType(ProcedureType pType) { |
| NamedStoredProcedureQueryMetadata storedProc = new NamedStoredProcedureQueryMetadata(); |
| storedProc.setName(getQueryNameForProcedureType(pType)); |
| storedProc.setProcedureName(pType.getProcedureName()); |
| storedProc.setReturnsResultSet(false); |
| // process the procedure's arguments |
| if (pType.getArguments().size() > 0) { |
| List<StoredProcedureParameterMetadata> params = new ArrayList<StoredProcedureParameterMetadata>(); |
| for (ArgumentType arg : pType.getArguments()) { |
| params.add(processArgument(arg)); |
| } |
| storedProc.setParameters(params); |
| } |
| return storedProc; |
| } |
| |
| /** |
| * Generate a PL/SQL stored function query based on the given FunctionType. |
| */ |
| protected NamedPLSQLStoredFunctionQueryMetadata processPLSQLFunctionType(FunctionType fType, PLSQLPackageType pkgType) { |
| NamedPLSQLStoredFunctionQueryMetadata storedFunc = new NamedPLSQLStoredFunctionQueryMetadata(); |
| storedFunc.setName(getQueryNameForProcedureType(fType)); |
| storedFunc.setProcedureName(pkgType.getPackageName() + DOT + fType.getProcedureName()); |
| List<PLSQLParameterMetadata> params = new ArrayList<PLSQLParameterMetadata>(); |
| // set the return parameter |
| storedFunc.setReturnParameter(processPLSQLArgument(fType.getReturnArgument())); |
| // process the function's arguments |
| if (fType.getArguments().size() > 0) { |
| for (ArgumentType arg : fType.getArguments()) { |
| params.add(processPLSQLArgument(arg)); |
| } |
| } |
| storedFunc.setParameters(params); |
| return storedFunc; |
| } |
| |
| /** |
| * Generate a PL/SQL stored procedure query based on the given ProcedureType. |
| */ |
| protected NamedPLSQLStoredProcedureQueryMetadata processPLSQLProcedureType(ProcedureType pType, PLSQLPackageType pkgType) { |
| NamedPLSQLStoredProcedureQueryMetadata storedProc = new NamedPLSQLStoredProcedureQueryMetadata(); |
| storedProc.setName(getQueryNameForProcedureType(pType)); |
| storedProc.setProcedureName(pkgType.getPackageName() + DOT + pType.getProcedureName()); |
| // process the procedure's arguments |
| if (pType.getArguments().size() > 0) { |
| List<PLSQLParameterMetadata> params = new ArrayList<PLSQLParameterMetadata>(); |
| for (ArgumentType arg : pType.getArguments()) { |
| params.add(processPLSQLArgument(arg)); |
| } |
| storedProc.setParameters(params); |
| } |
| return storedProc; |
| } |
| |
| /** |
| * Convenience method that returns a query name for a given ProcedureType. |
| * The name will be the procedureName value of the ProcedureType with |
| * "_" + overload value if the ProcedureType's overload value is > 0. |
| * |
| * For example, if the procedureName value is "P1" and overload == 0, "P1" |
| * is returned. If the procedureName value is "P1" and overload == 4, |
| * "P1_4" is returned. |
| */ |
| protected String getQueryNameForProcedureType(ProcedureType pType) { |
| return pType.getOverload() == 0 ? pType.getProcedureName() : pType.getProcedureName() + UNDERSCORE + pType.getOverload(); |
| } |
| |
| /** |
| * Generate a stored procedure parameter based on the given ArgumentType. |
| * For PL/SQL arguments the processPLSQLArgument method should be used. |
| */ |
| protected StoredProcedureParameterMetadata processArgument(ArgumentType arg) { |
| StoredProcedureParameterMetadata param = new StoredProcedureParameterMetadata(); |
| param.setName(arg.getArgumentName()); |
| // don't set mode for stored function return argument |
| if (arg.getDirection() != ArgumentTypeDirection.RETURN) { |
| param.setMode(arg.getDirection().name()); |
| } |
| if (!arg.isComposite()) { |
| param.setTypeName(getClassNameFromJDBCTypeName(arg.getTypeName(), dbPlatform)); |
| param.setJdbcType(getJDBCTypeFromTypeName(arg.getTypeName())); |
| param.setJdbcTypeName(getJDBCTypeName(arg.getTypeName())); |
| } else { // handle composites, i.e. Object, Varray, PL/SQL, etc. |
| param.setTypeName(getGeneratedJavaClassName(arg.getTypeName(), defaultPackage)); |
| param.setJdbcTypeName(arg.getTypeName()); |
| if (arg.isObjectType()) { // ObjectType |
| param.setJdbcType(Types.STRUCT); |
| } else if (arg.isObjectTableType() || arg.isVArrayType()) { // ObjectTable and Varray |
| param.setJdbcType(Types.ARRAY); |
| } |
| processCompositeType(arg.getEnclosedType()); |
| } |
| return param; |
| } |
| |
| /** |
| * Generate a PL/SQL parameter based on the given ArgumentType. For |
| * non-PL/SQL arguments the processArgument method should be used. |
| */ |
| protected PLSQLParameterMetadata processPLSQLArgument(ArgumentType arg) { |
| // for %ROWTYPE, we need to create a PL/SQL record that mirrors the Table |
| if (arg.getEnclosedType().isROWTYPEType()) { |
| ROWTYPEType rType = (ROWTYPEType) arg.getEnclosedType(); |
| TableType tableType = (TableType) rType.getEnclosedType(); |
| PLSQLRecordType plsqlRec = new PLSQLRecordType(rType.getTypeName()); |
| plsqlRec.setParentType(new PLSQLPackageType()); |
| for (FieldType col : tableType.getColumns()) { |
| FieldType ft = new FieldType(col.getFieldName()); |
| ft.setEnclosedType(col.getEnclosedType()); |
| plsqlRec.addField(ft); |
| } |
| arg.setEnclosedType(plsqlRec); |
| } |
| |
| PLSQLParameterMetadata param = new PLSQLParameterMetadata(); |
| // handle cursor |
| if (arg.isPLSQLCursorType()) { |
| param.setDirection(OUT_CURSOR_STR); |
| } |
| // handle stored function return type |
| if (arg.getDirection() == ArgumentTypeDirection.RETURN) { |
| param.setName(arg.isPLSQLCursorType() ? CURSOR_STR : RESULT_STR); |
| } else { |
| // direction is already set for cursor type |
| if (!arg.isPLSQLCursorType()) { |
| param.setDirection(arg.getDirection().name()); |
| } |
| param.setName(arg.getArgumentName()); |
| } |
| |
| String dbType = arg.getTypeName(); |
| // handle composites |
| if (arg.isComposite()) { |
| DatabaseType enclosedType = arg.getEnclosedType(); |
| // need to prepend the package name for most PL/SQL and Cursor types |
| if (enclosedType.isPLSQLType() || enclosedType.isPLSQLCursorType()) { |
| dbType = getQualifiedTypeName(enclosedType); |
| } |
| // process the composite enclosed type |
| processCompositeType(enclosedType, dbType); |
| } |
| param.setDatabaseType(processTypeName(dbType)); |
| return param; |
| } |
| |
| /** |
| * Generate object type metadata based on the given ObjectType. |
| */ |
| protected OracleObjectTypeMetadata processObjectType(ObjectType oType) { |
| OracleObjectTypeMetadata objectType = new OracleObjectTypeMetadata(); |
| objectType.setName(oType.getTypeName()); |
| objectType.setJavaType(getGeneratedJavaClassName(oType.getTypeName(), defaultPackage)); |
| // process the object type's fields |
| List<PLSQLParameterMetadata> fields = new ArrayList<PLSQLParameterMetadata>(); |
| for (FieldType ft : oType.getFields()) { |
| PLSQLParameterMetadata fieldMetadata = new PLSQLParameterMetadata(); |
| fieldMetadata.setName(ft.getFieldName()); |
| fieldMetadata.setDatabaseType(processTypeName(ft.getTypeName())); |
| fields.add(fieldMetadata); |
| if (ft.isComposite()) { |
| processCompositeType(ft.getEnclosedType()); |
| } |
| } |
| objectType.setFields(fields); |
| |
| // avoid double-processing |
| getProcessedTypes().add(objectType.getName()); |
| |
| // generate an EmbeddableAccessor for this type |
| generateEmbeddable(objectType, oType); |
| |
| return objectType; |
| } |
| |
| /** |
| * Generate array type metadata based on the given VArray or ObjectTable type. |
| */ |
| protected OracleArrayTypeMetadata processArrayType(DatabaseType dbType) { |
| OracleArrayTypeMetadata arrayType = new OracleArrayTypeMetadata(); |
| arrayType.setName(dbType.getTypeName()); |
| arrayType.setJavaType(getGeneratedJavaClassName(dbType.getTypeName(), defaultPackage)); |
| if (dbType.isVArrayType()) { |
| arrayType.setNestedType(processTypeName(((VArrayType) dbType).getEnclosedType().getTypeName())); |
| } else { |
| // assumes ObjectTable |
| arrayType.setNestedType(((ObjectTableType) dbType).getEnclosedType().getTypeName()); |
| } |
| // avoid double-processing |
| getProcessedTypes().add(arrayType.getName()); |
| |
| // generate an EmbeddableAccessor for this type |
| generateEmbeddable(arrayType, (CompositeDatabaseTypeWithEnclosedType) dbType); |
| |
| return arrayType; |
| } |
| |
| /** |
| * Process the given PLSQLCollectionType and return a PLSQLTableMetadata instance. |
| * |
| */ |
| protected PLSQLTableMetadata processPLSQLCollectionType(PLSQLCollectionType plsqlCollectionType) { |
| String typeName = getQualifiedTypeName(plsqlCollectionType); |
| String compatiableName = getQualifiedCompatibleTypeName(plsqlCollectionType); |
| String targetClassName = compatiableName; |
| |
| PLSQLTableMetadata plsqlTable = new PLSQLTableMetadata(); |
| plsqlTable.setName(typeName); |
| plsqlTable.setCompatibleType(compatiableName); |
| plsqlTable.setJavaType(getGeneratedJavaClassName(typeName)); |
| |
| // handle Nested Table (i.e. non-Varray) |
| plsqlTable.setNestedTable(!plsqlCollectionType.isIndexed()); |
| String dbType = plsqlCollectionType.getEnclosedType().getTypeName(); |
| if (!(getJDBCTypeFromTypeName(dbType) == Types.OTHER)) { |
| // need special handling for nested PL/SQL scalar types |
| if (isArgPLSQLScalar(dbType)) { |
| plsqlTable.setNestedType(getOraclePLSQLTypeForName(dbType)); |
| } else { |
| plsqlTable.setNestedType(processTypeName(dbType)); |
| } |
| } else { |
| if (plsqlCollectionType.isComposite()) { |
| DatabaseType enclosedType = plsqlCollectionType.getEnclosedType(); |
| // may need to prepend package name |
| if (enclosedType.isPLSQLType()) { |
| dbType = ((PLSQLType) enclosedType).getParentType().getPackageName() + DOT + dbType; |
| targetClassName = getGeneratedJavaClassName(dbType); |
| } else { |
| // advanced JDBC |
| targetClassName = getGeneratedJavaClassName(dbType, defaultPackage); |
| } |
| processCompositeType(enclosedType, dbType); |
| } |
| plsqlTable.setNestedType(dbType); |
| } |
| // avoid double-processing |
| getProcessedTypes().add(plsqlTable.getName()); |
| |
| // generate an EmbeddableAccessor for this type |
| generateEmbeddable(plsqlTable, targetClassName); |
| |
| return plsqlTable; |
| } |
| |
| /** |
| * Process the given PLSQLRecordType and return a PLSQLRecordMetadata instance. |
| * |
| */ |
| protected PLSQLRecordMetadata processPLSQLRecordType(PLSQLRecordType plsqlRecordType) { |
| // for %ROWTYPE we create a 'place holder' PL/SQL Record - in this case there is no package name |
| String typeName = getQualifiedTypeName(plsqlRecordType); |
| String compatibleName = getQualifiedCompatibleTypeName(plsqlRecordType); |
| if (compatibleName.contains(PERCENT)) { |
| compatibleName = compatibleName.replace(PERCENT, UNDERSCORE); |
| } |
| |
| PLSQLRecordMetadata plsqlRecord = new PLSQLRecordMetadata(); |
| plsqlRecord.setName(typeName); |
| plsqlRecord.setCompatibleType(compatibleName); |
| if (typeName.endsWith(ROWTYPE_STR)) { |
| plsqlRecord.setJavaType(getGeneratedJavaClassName(compatibleName)); |
| } else { |
| plsqlRecord.setJavaType(getGeneratedJavaClassName(typeName)); |
| } |
| |
| List<PLSQLParameterMetadata> fields = new ArrayList<PLSQLParameterMetadata>(); |
| PLSQLParameterMetadata field; |
| for (FieldType fld : plsqlRecordType.getFields()) { |
| field = new PLSQLParameterMetadata(); |
| field.setName(fld.getFieldName()); |
| String dbType = processTypeName(fld.getTypeName()); |
| if (fld.isComposite()) { |
| DatabaseType enclosedType = fld.getEnclosedType(); |
| // may need to prepend package name |
| if (enclosedType.isPLSQLType()) { |
| dbType = ((PLSQLType) fld.getEnclosedType()).getParentType().getPackageName() + DOT + dbType; |
| } |
| processCompositeType(enclosedType, dbType); |
| } |
| field.setDatabaseType(dbType); |
| fields.add(field); |
| } |
| plsqlRecord.setFields(fields); |
| |
| // avoid double-processing |
| getProcessedTypes().add(plsqlRecord.getName()); |
| |
| // generate an EmbeddableAccessor for this type |
| generateEmbeddable(plsqlRecord, plsqlRecordType); |
| |
| return plsqlRecord; |
| } |
| |
| /** |
| * Process the given composite database type. |
| */ |
| protected void processCompositeType(DatabaseType compositeType) { |
| processCompositeType(compositeType, compositeType.getTypeName()); |
| } |
| /** |
| * Process the given composite database type. For PL/SQL types, typeName will be |
| * the fully qualified type name (i.e. packagename.typename). The type should |
| * be one of: PLSQLCollection, PLSQLRecord, Object, ObjectTable, or Varray. |
| */ |
| protected void processCompositeType(DatabaseType compositeType, String typeName) { |
| // avoid double-processing of records & collections, objects and arrays |
| if (!alreadyProcessed(typeName)) { |
| if (compositeType.isPLSQLCollectionType()) { |
| xmlEntityMappings.getPLSQLTables().add(processPLSQLCollectionType((PLSQLCollectionType) compositeType)); |
| } else if (compositeType.isPLSQLRecordType()) { |
| xmlEntityMappings.getPLSQLRecords().add(processPLSQLRecordType((PLSQLRecordType) compositeType)); |
| } else if (compositeType.isObjectType()) { |
| xmlEntityMappings.getOracleObjectTypes().add(processObjectType((ObjectType) compositeType)); |
| } else if (compositeType.isObjectTableType() || compositeType.isVArrayType()) { |
| xmlEntityMappings.getOracleArrayTypes().add(processArrayType(compositeType)); |
| } |
| } |
| } |
| |
| /** |
| * Generate an Embeddable for the given PLSQLTableMetadata, and add |
| * it to the list of Embeddables on the XMLEntityMappings instance. |
| * |
| * @param tableMetadata PLSQLTableMetadata used to build the Embeddable |
| */ |
| protected void generateEmbeddable(PLSQLTableMetadata tableMetadata, String targetClassName) { |
| // avoid double-processing |
| if (!embeddableAlreadyProcessed(tableMetadata.getJavaType())) { |
| EmbeddableAccessor embeddable = initEmbeddable(tableMetadata.getJavaType()); |
| |
| ArrayAccessor array = generateArrayAccessor(ITEMS_FLD_STR, ITEMS_COL_STR, tableMetadata.getCompatibleType(), targetClassName); |
| embeddable.getAttributes().getArrays().add(array); |
| |
| // set on the XMLEntityMappings instance |
| xmlEntityMappings.getEmbeddables().add(embeddable); |
| |
| // track to avoid double processing |
| getGeneratedEmbeddables().add(tableMetadata.getJavaType()); |
| } |
| } |
| |
| /** |
| * Generate an Embeddable for the given PLSQLRecordMetadata and PLSQLRecordType, |
| * and add it to the list of Embeddables on the XMLEntityMappings instance. |
| * |
| * @param recordMetadata PLSQLRecordMetadata used to build the Embeddable |
| * @param recordType PLSQLRecordType used to build the Embeddable |
| */ |
| protected void generateEmbeddable(PLSQLRecordMetadata recordMetadata, PLSQLRecordType recordType) { |
| // avoid double-processing |
| if (!embeddableAlreadyProcessed(recordMetadata.getJavaType())) { |
| EmbeddableAccessor embeddable = initEmbeddable(recordMetadata.getJavaType()); |
| |
| // add a struct to satisfy field ordering |
| StructMetadata struct = new StructMetadata(); |
| struct.setName(recordMetadata.getCompatibleType()); |
| List<String> fields = new ArrayList<String>(); |
| for (PLSQLParameterMetadata fld : recordMetadata.getFields()) { |
| fields.add(fld.getName()); |
| } |
| struct.setFields(fields); |
| embeddable.setStruct(struct); |
| |
| // add an attribute to the embeddable for each of the record's fields |
| addEmbeddableAttributes(embeddable, recordType.getFields()); |
| |
| // set on the XMLEntityMappings instance |
| xmlEntityMappings.getEmbeddables().add(embeddable); |
| |
| // track to avoid double processing |
| getGeneratedEmbeddables().add(recordMetadata.getJavaType()); |
| } |
| } |
| |
| /** |
| * Generate an Embeddable for the given OracleArrayTypeMetadata, and add |
| * it to the list of Embeddables on the XMLEntityMappings instance. |
| */ |
| protected void generateEmbeddable(OracleArrayTypeMetadata arrayTypeMetadata, CompositeDatabaseTypeWithEnclosedType dbType) { |
| // avoid double-processing |
| if (!embeddableAlreadyProcessed(arrayTypeMetadata.getJavaType())) { |
| EmbeddableAccessor embeddable = initEmbeddable(arrayTypeMetadata.getJavaType()); |
| |
| ArrayAccessor array; |
| if (dbType.getEnclosedType().isComposite()) { |
| array = generateArrayAccessor(ITEMS_FLD_STR, ITEMS_COL_STR, arrayTypeMetadata.getNestedType(), |
| getGeneratedJavaClassName(arrayTypeMetadata.getNestedType(), defaultPackage)); |
| } else { |
| array = generateArrayAccessor(ITEMS_FLD_STR, ITEMS_COL_STR, dbType.getEnclosedType().getTypeName()); |
| } |
| |
| embeddable.getAttributes().getArrays().add(array); |
| |
| // set on the XMLEntityMappings instance |
| xmlEntityMappings.getEmbeddables().add(embeddable); |
| |
| // track to avoid double processing |
| getGeneratedEmbeddables().add(arrayTypeMetadata.getJavaType()); |
| } |
| } |
| |
| /** |
| * Generate an Embeddable for the given OracleObjectTypeMetadata, and add |
| * it to the list of Embeddables on the XMLEntityMappings instance. |
| */ |
| protected void generateEmbeddable(OracleObjectTypeMetadata objectTypeMetadata, ObjectType objectType) { |
| // avoid double-processing |
| if (!embeddableAlreadyProcessed(objectTypeMetadata.getJavaType())) { |
| EmbeddableAccessor embeddable = initEmbeddable(objectTypeMetadata.getJavaType()); |
| |
| // add a struct to satisfy field ordering |
| StructMetadata struct = new StructMetadata(); |
| struct.setName(objectTypeMetadata.getName()); |
| List<String> fields = new ArrayList<String>(); |
| for (PLSQLParameterMetadata fld : objectTypeMetadata.getFields()) { |
| fields.add(fld.getName()); |
| } |
| struct.setFields(fields); |
| embeddable.setStruct(struct); |
| |
| // add an attribute to the embeddable for each of the object's fields |
| addEmbeddableAttributes(embeddable, objectType.getFields()); |
| |
| // set on the XMLEntityMappings instance |
| xmlEntityMappings.getEmbeddables().add(embeddable); |
| |
| // track to avoid double processing |
| getGeneratedEmbeddables().add(objectTypeMetadata.getJavaType()); |
| } |
| } |
| |
| /** |
| * Convenience method that creates and EmbeddableAccessor, setting the class name to the |
| * provided embeddableClassName, initializes the various lists (Basics, Arrays, etc.), |
| * and sets the access type to 'VIRTUAL'. |
| */ |
| protected EmbeddableAccessor initEmbeddable(String embeddableClassName) { |
| EmbeddableAccessor embeddable = new EmbeddableAccessor(); |
| embeddable.setClassName(embeddableClassName); |
| embeddable.setAccess(EL_ACCESS_VIRTUAL); |
| |
| // initialize the various lists - some used, some not |
| initializeXMLAttributeLists(embeddable); |
| return embeddable; |
| } |
| |
| /** |
| * Process a list of FieldTypes, creating an attribute for each - the created |
| * XMLAttributes are set on the given EmbeddableAccessor. |
| * |
| * @see org.eclipse.persistence.internal.jpa.metadata.accessors.classes.XMLAttributes |
| */ |
| protected void addEmbeddableAttributes(EmbeddableAccessor embeddable, List<FieldType> fields) { |
| for (FieldType fld : fields) { |
| DatabaseType enclosedType = fld.getEnclosedType(); |
| if (!enclosedType.isComposite() || enclosedType.isTYPEType()) { // basic |
| String typeName = enclosedType.isTYPEType() ? enclosedType.getTypeName() : fld.getTypeName(); |
| BasicAccessor basic = generateBasicAccessor(fld.getFieldName().toLowerCase(), fld.getFieldName(), getClassNameFromJDBCTypeName(typeName, dbPlatform)); |
| embeddable.getAttributes().getBasics().add(basic); |
| } else if (enclosedType.isPLSQLType()) { // record or collection |
| PLSQLType plsqlType = (PLSQLType) enclosedType; |
| String typeName = getQualifiedTypeName(plsqlType); |
| EmbeddedAccessor embedded = new EmbeddedAccessor(); |
| embedded.setName(fld.getFieldName().toLowerCase()); |
| embedded.setAttributeType(getGeneratedJavaClassName(typeName)); |
| embeddable.getAttributes().getEmbeddeds().add(embedded); |
| } else if (enclosedType.isVArrayType() || enclosedType.isObjectTableType()) { // array |
| ArrayAccessor array = null; |
| // target class is reference class name for Object Table, and structure name for Varray |
| if (enclosedType.isVArrayType()) { |
| array = generateArrayAccessor(fld.getFieldName().toLowerCase(), fld.getFieldName(), enclosedType.getTypeName()); |
| } else { |
| ObjectTableType otType = (ObjectTableType) enclosedType; |
| array = generateArrayAccessor(fld.getFieldName().toLowerCase(), fld.getFieldName(), otType.getEnclosedType().getTypeName(), |
| getGeneratedJavaClassName(otType.getEnclosedType().getTypeName(), defaultPackage)); |
| } |
| embeddable.getAttributes().getArrays().add(array); |
| } else if (enclosedType.isObjectType()) { // struct |
| StructureAccessor structure = generateStructureAccessor(fld.getFieldName().toLowerCase(), fld.getFieldName(), |
| getGeneratedJavaClassName(enclosedType.getTypeName(), defaultPackage)); |
| embeddable.getAttributes().getStructures().add(structure); |
| } else if (enclosedType.isTYPEType()) { |
| TYPEType tType = (TYPEType) enclosedType; |
| BasicAccessor basic = generateBasicAccessor(fld.getFieldName().toLowerCase(), fld.getFieldName(), getClassNameFromJDBCTypeName(tType.getTypeName(), dbPlatform)); |
| embeddable.getAttributes().getBasics().add(basic); |
| } |
| } |
| } |
| |
| /** |
| * Returns an ArrayAccessor instance, constructed based on the given String values. This method |
| * can be used when the database type and target class names are the same. |
| * |
| */ |
| protected ArrayAccessor generateArrayAccessor(String arrayName, String columnName, String databaseTypeName) { |
| return generateArrayAccessor(arrayName, columnName, databaseTypeName, databaseTypeName); |
| } |
| |
| /** |
| * Returns an ArrayAccessor instance, constructed based on the given String values. |
| */ |
| protected ArrayAccessor generateArrayAccessor(String arrayName, String columnName, String databaseTypeName, String targetClassName) { |
| ArrayAccessor array = new ArrayAccessor(); |
| array.setName(arrayName); |
| array.setAttributeType(ARRAYLIST_CLS_STR); |
| array.setDatabaseType(databaseTypeName); |
| array.setTargetClassName(targetClassName); |
| ColumnMetadata column = new ColumnMetadata(); |
| column.setName(columnName); |
| array.setColumn(column); |
| return array; |
| } |
| |
| /** |
| * Returns a BasicAccessor instance, constructed based on the given String values. |
| */ |
| protected BasicAccessor generateBasicAccessor(String basicName, String columnName, String attributeTypeName) { |
| BasicAccessor basic = new BasicAccessor(); |
| basic.setName(basicName); |
| basic.setAttributeType(attributeTypeName); |
| |
| ColumnMetadata column = new ColumnMetadata(); |
| column.setName(columnName); |
| basic.setColumn(column); |
| return basic; |
| } |
| |
| /** |
| * Returns a StructureAccessor instance, constructed based on the given String values. This method can be used |
| * when the attribute type and target class names are the same. |
| */ |
| protected StructureAccessor generateStructureAccessor(String structureName, String columnName, String attributeTypeName) { |
| return generateStructureAccessor(structureName, columnName, attributeTypeName, attributeTypeName); |
| } |
| |
| /** |
| * Returns a StructureAccessor instance, constructed based on the given String values. |
| */ |
| protected StructureAccessor generateStructureAccessor(String structureName, String columnName, String attributeTypeName, String targetClassName) { |
| StructureAccessor structure = new StructureAccessor(); |
| structure.setName(structureName); |
| structure.setAttributeType(attributeTypeName); |
| structure.setTargetClassName(targetClassName); |
| ColumnMetadata column = new ColumnMetadata(); |
| column.setName(columnName); |
| structure.setColumn(column); |
| return structure; |
| } |
| |
| /** |
| * Generates NamedNativeQueryMetadata for CRUD operations (create, |
| * findAll, findByPk, update and delete) for a given Entity if |
| * required, i.e. generateCRUDOps is true. |
| */ |
| protected void generateCRUDMetadata(EntityAccessor entity) { |
| if (generateCRUDOps) { |
| // don't blow away the Entity's query metadata |
| if (entity.getNamedNativeQueries() == null) { |
| entity.setNamedNativeQueries(new ArrayList<NamedNativeQueryMetadata>()); |
| } |
| |
| String tableName = entity.getTable().getName(); |
| String entityType = getUnqualifiedEntityName(tableName) + TYPE_STR; |
| |
| List<IdAccessor> ids = entity.getAttributes().getIds(); |
| List<BasicAccessor> basics = entity.getAttributes().getBasics(); |
| |
| // list of all mappings (ids and basics) |
| List<MappingAccessor> mappings = new ArrayList<MappingAccessor>(); |
| mappings.addAll(ids); |
| mappings.addAll(basics); |
| |
| // process primary keys |
| String pks = null; |
| int pkCount = 0; |
| for (IdAccessor pk : ids) { |
| if (pkCount++ == 0) { |
| pks = OPEN_BRACKET + pk.getName().toUpperCase() + EQUALS_BINDING1_STR; |
| } else { |
| pks = pks.concat(AND_STR + pk.getName().toUpperCase() + EQUALS_BINDING_STR + pkCount++); |
| } |
| } |
| if (pks != null) { |
| pks = pks.concat(CLOSE_BRACKET); |
| } |
| |
| // find by PK |
| NamedNativeQueryMetadata crudQuery = new NamedNativeQueryMetadata(); |
| crudQuery.setName(PK_QUERYNAME + UNDERSCORE + entityType); |
| crudQuery.setQuery(SELECT_FROM_STR + tableName + WHERE_STR + pks); |
| crudQuery.setResultClassName(entity.getClassName()); |
| entity.getNamedNativeQueries().add(crudQuery); |
| |
| // find all |
| crudQuery = new NamedNativeQueryMetadata(); |
| crudQuery.setName(ALL_QUERYNAME + UNDERSCORE + entityType); |
| crudQuery.setQuery(SELECT_FROM_STR + tableName); |
| crudQuery.setResultClassName(entity.getClassName()); |
| entity.getNamedNativeQueries().add(crudQuery); |
| // create |
| StringBuilder sqlStmt = new StringBuilder(128); |
| sqlStmt.append(INSERT_STR).append(tableName).append(SINGLE_SPACE).append(OPEN_BRACKET); |
| MetadataHelper.buildColsFromMappings(sqlStmt, mappings, COMMA_SPACE_STR); |
| sqlStmt.append(CLOSE_BRACKET).append(VALUES_STR).append(OPEN_BRACKET); |
| MetadataHelper.buildValuesAsQMarksFromMappings(sqlStmt, mappings, COMMA_SPACE_STR); |
| sqlStmt.append(CLOSE_BRACKET); |
| |
| crudQuery = new NamedNativeQueryMetadata(); |
| crudQuery.setName(CREATE_OPERATION_NAME + UNDERSCORE + entityType); |
| crudQuery.setQuery(sqlStmt.toString()); |
| entity.getNamedNativeQueries().add(crudQuery); |
| |
| // update |
| sqlStmt = new StringBuilder(128); |
| sqlStmt.append(UPDATE_STR).append(tableName).append(SET_STR); |
| MetadataHelper.buildColsAndValuesBindingsFromMappings(sqlStmt, basics, |
| pkCount, EQUALS_BINDING_STR, COMMA_SPACE_STR); |
| sqlStmt.append(WHERE_STR).append(pks); |
| |
| crudQuery = new NamedNativeQueryMetadata(); |
| crudQuery.setName(UPDATE_OPERATION_NAME + UNDERSCORE + entityType); |
| crudQuery.setQuery(sqlStmt.toString()); |
| entity.getNamedNativeQueries().add(crudQuery); |
| |
| // delete |
| crudQuery = new NamedNativeQueryMetadata(); |
| crudQuery.setName(REMOVE_OPERATION_NAME + UNDERSCORE + entityType); |
| crudQuery.setQuery(DELETE_STR + tableName + WHERE_STR + pks); |
| entity.getNamedNativeQueries().add(crudQuery); |
| } |
| } |
| |
| /** |
| * If set to true, NamedNativeQueryMetadata for CRUD operations (create, findAll, findByPk, |
| * update and delete) will be generated for each Entity. The default is false. |
| * |
| */ |
| protected void setGenerateCRUDOps(boolean generateCRUDOps) { |
| this.generateCRUDOps = generateCRUDOps; |
| } |
| |
| /** |
| * Lazy-load the List of processed composite types. |
| */ |
| protected List<String> getProcessedTypes() { |
| if (processedTypes == null) { |
| processedTypes = new ArrayList<String>(); |
| } |
| return processedTypes; |
| } |
| /** |
| * Lazy-load the List of embeddables. |
| */ |
| protected List<String> getGeneratedEmbeddables() { |
| if (generatedEmbeddables == null) { |
| generatedEmbeddables = new ArrayList<String>(); |
| } |
| return generatedEmbeddables; |
| } |
| |
| /** |
| * Indicates if an embeddable has already been processed - the list of |
| * generated embeddable names will be checked for the given typeName. |
| */ |
| protected boolean embeddableAlreadyProcessed(String embeddableName) { |
| return generatedEmbeddables != null && generatedEmbeddables.size() > 0 && generatedEmbeddables.contains(embeddableName); |
| } |
| |
| /** |
| * Indicates if a type has already been processed - the list of |
| * processed type names will be checked for the given typeName. |
| */ |
| protected boolean alreadyProcessed(String typeName) { |
| return processedTypes != null && processedTypes.size() > 0 && processedTypes.contains(typeName); |
| } |
| |
| /** |
| * Attempt to load the DatabasePlatform using the given platform class name. If the |
| * platform cannot be loaded Oracle11Platform will be returned - if available. |
| * |
| * @param platformClassName class name of the DatabasePlatform to be loaded |
| * @return DatabasePlatform loaded for the given platformClassname, or Oracle11Platform if not found |
| * @see "org.eclipse.persistence.platform.database.oracle.Oracle11Platform" |
| */ |
| public static DatabasePlatform loadDatabasePlatform(String platformClassName) { |
| DatabasePlatform dbPlatform = null; |
| Class<?> platformClass = null; |
| try { |
| if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ |
| platformClass = AccessController.doPrivileged(new PrivilegedClassForName(platformClassName)); |
| } else { |
| platformClass = PrivilegedAccessHelper.getClassForName(platformClassName); |
| } |
| dbPlatform = (DatabasePlatform) Helper.getInstanceFromClass(platformClass); |
| } catch (PrivilegedActionException | ClassNotFoundException | NullPointerException e) { |
| try { |
| if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ |
| platformClass = AccessController.doPrivileged(new PrivilegedClassForName(DEFAULT_PLATFORM)); |
| } else { |
| platformClass = PrivilegedAccessHelper.getClassForName(DEFAULT_PLATFORM); |
| } |
| dbPlatform = (DatabasePlatform) Helper.getInstanceFromClass(platformClass); |
| } catch (PrivilegedActionException | ClassNotFoundException ex) { |
| // at this point we can't load the default Oracle11Platform, so null will be returned |
| } |
| } |
| return dbPlatform; |
| } |
| } |