| /* |
| * 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: |
| // Oracle - initial API and implementation from Oracle TopLink |
| // 09/09/2011-2.3.1 Guy Pelletier |
| // - 356197: Add new VPD type to MultitenantType |
| // 09/14/2011-2.3.1 Guy Pelletier |
| // - 357533: Allow DDL queries to execute even when Multitenant entities are part of the PU |
| // 02/04/2013-2.5 Guy Pelletier |
| // - 389090: JPA 2.1 DDL Generation Support |
| package org.eclipse.persistence.tools.schemaframework; |
| |
| import java.io.*; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform; |
| import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition; |
| import org.eclipse.persistence.internal.helper.*; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.exceptions.*; |
| import org.eclipse.persistence.queries.*; |
| |
| /** |
| * <p> |
| * <b>Purpose</b>: Define a database object for the purpose of creation and deletion. |
| * A database object is an entity such as a table, view, proc, sequence... |
| * <p> |
| * <b>Responsibilities</b>: |
| * <ul> |
| * <li> Be able to create and drop the object from the database. |
| * </ul> |
| */ |
| public abstract class DatabaseObjectDefinition implements Cloneable, Serializable { |
| public String name; |
| public String qualifier; |
| |
| /** |
| * INTERNAL: |
| * Retrieve a database platform specific definition from session for |
| * existing type instance or build a new one when type is {@code null}. |
| * @param session Session to search for already existing instances. |
| * @param type Field type class. |
| * @param name Filed type name. |
| * @return Database platform specific definition instance. |
| * @throws ValidationException when provided type is not valid database type. |
| */ |
| protected static final FieldTypeDefinition getFieldTypeDefinition( |
| final AbstractSession session, final Class<?> type, final String name) { |
| final FieldTypeDefinition fieldType = type != null |
| ? session.getPlatform().getFieldTypeDefinition(type) |
| : new FieldTypeDefinition(name); |
| if (fieldType == null) { |
| throw ValidationException.javaTypeIsNotAValidDatabaseType(type); |
| } |
| return fieldType; |
| } |
| |
| /** |
| * INTERNAL: |
| * Retrieve database platform specific field definition from database |
| * specific platform handler for existing type or build a new one when type |
| * is {@code null} and type for type name could not be found. |
| * @param platform Specific database platform handler. |
| * @param type Field type (will be processed first when available). |
| * @param name Field type name (will be processed as backup option when |
| * type class is not available). |
| * @throws ValidationException when provided type is not valid database type. |
| */ |
| protected static final FieldTypeDefinition getFieldTypeDefinition( |
| final DatabasePlatform platform, final Class<?> type, final String name) { |
| FieldTypeDefinition fieldType; |
| if (type != null) { //translate Java 'type' |
| fieldType = platform.getFieldTypeDefinition(type); |
| if (fieldType == null) { |
| throw ValidationException.javaTypeIsNotAValidDatabaseType(type); |
| } |
| } else if (name != null) { //translate generic type name |
| final Map<String, Class<?>> fieldTypes = platform.getClassTypes(); |
| final Class<?> typeFromName = fieldTypes.get(name); |
| if (typeFromName == null) { // if unknown type name, use as it is |
| fieldType = new FieldTypeDefinition(name); |
| } else { |
| fieldType = platform.getFieldTypeDefinition(typeFromName); |
| if (fieldType == null) { |
| throw ValidationException.javaTypeIsNotAValidDatabaseType(typeFromName); |
| } |
| } |
| } else { |
| // Both type and typeName is null |
| throw ValidationException.javaTypeIsNotAValidDatabaseType(null); |
| } |
| return fieldType; |
| } |
| |
| protected DatabaseObjectDefinition() { |
| this.name = ""; |
| this.qualifier = ""; |
| } |
| |
| /** |
| * INTERNAL: |
| * Returns the writer used for creation of this object. |
| */ |
| public abstract Writer buildCreationWriter(AbstractSession session, Writer writer) throws ValidationException; |
| |
| /** |
| * INTERNAL: |
| * Sub classes should override. |
| */ |
| public Writer buildVPDCreationPolicyWriter(AbstractSession session, Writer writer) { |
| // Does nothing .. subclasses should override |
| return null; |
| } |
| |
| /** |
| * INTERNAL: |
| * Sub classes should override. |
| */ |
| public Writer buildVPDCreationFunctionWriter(AbstractSession session, Writer writer) { |
| // Does nothing .. subclasses should override |
| return null; |
| } |
| |
| /** |
| * INTERNAL: |
| * Sub classes should override. |
| */ |
| public Writer buildVPDDeletionWriter(AbstractSession session, Writer writer) { |
| // Does nothing .. subclasses should override |
| return null; |
| } |
| |
| /** |
| * INTERNAL: |
| * Returns the writer used for deletion of this object. |
| */ |
| public abstract Writer buildDeletionWriter(AbstractSession session, Writer writer) throws ValidationException; |
| |
| /** |
| * PUBLIC: |
| */ |
| @Override |
| public Object clone() { |
| try { |
| return super.clone(); |
| } catch (CloneNotSupportedException impossible) { |
| return null; |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the DDL to create the database schema for this object. |
| * Does nothing at this level, subclasses that support this must override |
| * this method. |
| * |
| * @see TableDefinition |
| */ |
| public void createDatabaseSchema(AbstractSession session, Writer writer, Set<String> createdDatabaseSchemas) throws EclipseLinkException {} |
| |
| /** |
| * INTERNAL: |
| * Execute the DDL to create the database schema for this object. |
| * Does nothing at this level, subclasses that support this must override |
| * this method. |
| * |
| * @see TableDefinition |
| */ |
| public void createDatabaseSchemaOnDatabase(AbstractSession session, Set<String> createdDatabaseSchemas) throws EclipseLinkException {} |
| |
| /** |
| * INTERNAL: |
| * Either drop from the database directly or write the statement to a file. |
| * Database objects are root level entities such as tables, views, procs, sequences... |
| */ |
| public void createObject(AbstractSession session, Writer schemaWriter) throws EclipseLinkException { |
| if (schemaWriter == null) { |
| this.createOnDatabase(session); |
| } else { |
| this.buildCreationWriter(session, schemaWriter); |
| |
| if (shouldCreateVPDCalls(session)) { |
| buildVPDCreationPolicyWriter(session, schemaWriter); |
| buildVPDCreationFunctionWriter(session, schemaWriter); |
| } |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the DDL to create this object. |
| */ |
| public void createOnDatabase(AbstractSession session) throws EclipseLinkException { |
| session.priviledgedExecuteNonSelectingCall(new SQLCall(buildCreationWriter(session, new StringWriter()).toString())); |
| |
| if (shouldCreateVPDCalls(session)) { |
| session.priviledgedExecuteNonSelectingCall(new SQLCall(buildVPDCreationPolicyWriter(session, new StringWriter()).toString())); |
| session.priviledgedExecuteNonSelectingCall(new SQLCall(buildVPDCreationFunctionWriter(session, new StringWriter()).toString())); |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Subclasses who care should override this method, e.g. TableDefinition. |
| */ |
| public boolean shouldCreateDatabaseSchema(Set<String> createdDatabaseSchemas) { |
| return false; |
| } |
| |
| /** |
| * INTERNAL: |
| * Subclasses who care should override this method. |
| */ |
| public boolean shouldCreateVPDCalls(AbstractSession session) { |
| return false; |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the DDL to drop the database schema for this object. |
| * Does nothing at this level, subclasses that support this must override |
| * this method. |
| * |
| * @see TableDefinition |
| */ |
| public void dropDatabaseSchema(AbstractSession session, Writer writer) throws EclipseLinkException {} |
| |
| /** |
| * INTERNAL: |
| * Execute the DDL to drop the database schema for this object. |
| * Does nothing at this level, subclasses that support this must override |
| * this method. |
| * |
| * @see TableDefinition |
| */ |
| public void dropDatabaseSchemaOnDatabase(AbstractSession session) throws EclipseLinkException {} |
| |
| /** |
| * INTERNAL: |
| * Execute the DDL to drop the object. |
| */ |
| public void dropFromDatabase(AbstractSession session) throws EclipseLinkException { |
| session.priviledgedExecuteNonSelectingCall(new SQLCall(buildDeletionWriter(session, new StringWriter()).toString())); |
| |
| if (shouldCreateVPDCalls(session)) { |
| session.priviledgedExecuteNonSelectingCall(new SQLCall(buildVPDDeletionWriter(session, new StringWriter()).toString())); |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the DDL to drop the object. Either directly from the database |
| * of write out the statement to a file. |
| */ |
| public void dropObject(AbstractSession session, Writer schemaWriter, boolean createSQLFiles) throws EclipseLinkException { |
| if (schemaWriter == null) { |
| this.dropFromDatabase(session); |
| } else { |
| buildDeletionWriter(session, schemaWriter); |
| |
| if (shouldCreateVPDCalls(session)) { |
| buildVPDDeletionWriter(session, schemaWriter); |
| } |
| } |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the database schema associated with this database object. |
| * |
| * @see TableDefinition |
| */ |
| public String getDatabaseSchema() { |
| return null; |
| } |
| |
| /** |
| * INTERNAL: |
| * Most major databases support a creator name scope. |
| * This means whenever the database object is referenced, it must be qualified. |
| */ |
| public String getFullName() { |
| if (getQualifier().equals("")) { |
| return getName(); |
| } else { |
| return getQualifier() + "." + getName(); |
| } |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the name of the object. |
| * i.e. the table name or the sequence name. |
| */ |
| public String getName() { |
| return name; |
| } |
| |
| /** |
| * PUBLIC: |
| * Most major databases support a creator name scope. |
| * This means whenever the database object is referenced, it must be qualified. |
| */ |
| public String getQualifier() { |
| return qualifier; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return true is this database object definition has a schema definition. |
| */ |
| protected boolean hasDatabaseSchema() { |
| return getDatabaseSchema() != null && ! getDatabaseSchema().equals(""); |
| } |
| |
| /** |
| * Execute any statements required after the creation of the object |
| */ |
| public void postCreateObject(AbstractSession session, Writer createSchemaWriter, boolean createSQLFiles){ |
| } |
| |
| /** |
| * Execute any statements required before the deletion of the object |
| */ |
| public void preDropObject(AbstractSession session, Writer dropSchemaWriter, boolean createSQLFiles){ |
| } |
| |
| /** |
| * PUBLIC: |
| * Set the name of the object. |
| * i.e. the table name or the sequence name. |
| */ |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| /** |
| * PUBLIC: |
| * Most major databases support a creator name scope. |
| * This means whenever the database object is referenced, it must be qualified. |
| */ |
| public void setQualifier(String qualifier) { |
| this.qualifier = qualifier; |
| } |
| |
| @Override |
| public String toString() { |
| return Helper.getShortClassName(getClass()) + "(" + getFullName() + ")"; |
| } |
| } |