blob: 7128406a53750e12070664291d76eeca7ce81e2e [file] [log] [blame]
/*
* 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 - Dec 2008
package org.eclipse.persistence.internal.helper;
import java.util.ListIterator;
import java.util.List;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredProcedureCall;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLargument;
import org.eclipse.persistence.queries.StoredProcedureCall;
import org.eclipse.persistence.sessions.DatabaseRecord;
import static org.eclipse.persistence.internal.helper.DatabaseType.DatabaseTypeHelper.databaseTypeHelper;
import static org.eclipse.persistence.internal.helper.Helper.NL;
/**
* <b>PUBLIC</b>: Abstract class for Complex Database types
* (e.g. PL/SQL records, PL/SQL collections)
*
* @author Mike Norman - michael.norman@oracle.com
* @since Oracle TopLink 11.x.x
*/
public abstract class ComplexDatabaseType implements DatabaseType, Cloneable {
protected String typeName;
protected String compatibleType;
/**
* Defines the Java class that the complex type maps to.
*/
protected Class javaType;
protected String javaTypeName;
public boolean isRecord() {
return false;
}
public boolean isCollection() {
return false;
}
public boolean isStruct() {
return false;
}
public boolean isArray() {
return false;
}
/**
* Indicates if a given subclass represents a PL/SQL cursor.
*
* @see org.eclipse.persistence.platform.database.oracle.plsql.PLSQLCursor
*/
public boolean isCursor() {
return false;
}
@Override
public int getConversionCode() {
return getSqlCode();
}
@Override
public boolean isComplexDatabaseType() {
return true;
}
@Override
public boolean isJDBCType() {
return false;
}
public boolean hasCompatibleType() {
return this.compatibleType != null;
}
public String getCompatibleType() {
return compatibleType;
}
public void setCompatibleType(String compatibleType) {
this.compatibleType = compatibleType;
}
@Override
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
/**
* Set the Java class that the complex type maps to.
* The mapped class for a Record type, and collection class for Collection type.
*/
public void setJavaType(Class javaType) {
this.javaType = javaType;
if (javaType != null) {
javaTypeName = javaType.getName();
}
}
/**
* Return the Java class that the complex type maps to.
*/
public Class getJavaType() {
return javaType;
}
public String getJavaTypeName() {
if (javaType != null && javaTypeName == null) {
javaTypeName = javaType.getName();
}
return javaTypeName;
}
public void setJavaTypeName(String javaTypeName) {
this.javaTypeName = javaTypeName;
}
@Override
public ComplexDatabaseType clone() {
try {
ComplexDatabaseType clone = (ComplexDatabaseType)super.clone();
return clone;
}
catch (CloneNotSupportedException exception) {
throw new InternalError(exception.getMessage());
}
}
@Override
public void buildInDeclare(StringBuilder sb, PLSQLargument inArg) {
// Validate.
if (!hasCompatibleType()) {
throw QueryException.compatibleTypeNotSet(this);
}
if ((getTypeName() == null) || getTypeName().equals("")) {
throw QueryException.typeNameNotSet(this);
}
sb.append(" ");
sb.append(databaseTypeHelper.buildTarget(inArg));
sb.append(" ");
sb.append(getTypeName());
sb.append(";");
sb.append(NL);
sb.append(" ");
sb.append(databaseTypeHelper.buildCompatible(inArg));
sb.append(" ");
sb.append(getCompatibleType());
sb.append(" := :");
sb.append(inArg.inIndex);
sb.append(";");
sb.append(NL);
}
@Override
public void buildOutDeclare(StringBuilder sb, PLSQLargument outArg) {// Validate.
if (!hasCompatibleType()) {
throw QueryException.compatibleTypeNotSet(this);
}
if ((getTypeName() == null) || getTypeName().equals("")) {
throw QueryException.typeNameNotSet(this);
}
sb.append(" ");
sb.append(databaseTypeHelper.buildTarget(outArg));
sb.append(" ");
sb.append(getTypeName());
sb.append(";");
sb.append(NL);
}
@Override
public void buildBeginBlock(StringBuilder sb, PLSQLargument arg, PLSQLStoredProcedureCall call) {
String conversionRoutine = ((this.getTypeName().equals(this.getCompatibleType()))) ? call.getPl2SQLName(this) : call.getSQL2PlName(this);
if (conversionRoutine == null) {
// TODO exception
throw new NullPointerException("no SQL2Pl or Pl2SQL conversion routine for " + typeName);
}
String target = databaseTypeHelper.buildTarget(arg);
String compat = databaseTypeHelper.buildCompatible(arg);
sb.append(" ");
sb.append(target);
sb.append(" := ");
sb.append(conversionRoutine);
sb.append("(");
sb.append(compat);
sb.append(");");
sb.append(NL);
}
@Override
public void buildOutAssignment(StringBuilder sb, PLSQLargument outArg, PLSQLStoredProcedureCall call) {
String sql2PlName = call.getPl2SQLName(this);
if (sql2PlName == null) {
// TODO: Error.
throw new NullPointerException("no Pl2SQL conversion routine for " + typeName);
}
String target = databaseTypeHelper.buildTarget(outArg);
sb.append(" :");
sb.append(outArg.outIndex);
sb.append(" := ");
sb.append(sql2PlName);
sb.append("(");
sb.append(target);
sb.append(");");
sb.append(NL);
}
@Override
public void buildOutputRow(PLSQLargument outArg, AbstractRecord outputRow,
DatabaseRecord newOutputRow, List<DatabaseField> outputRowFields, List outputRowValues) {
databaseTypeHelper.buildOutputRow(outArg, outputRow,
newOutputRow, outputRowFields, outputRowValues);
}
@Override
public int computeInIndex(PLSQLargument inArg, int newIndex, ListIterator<PLSQLargument> i) {
return databaseTypeHelper.computeInIndex(inArg, newIndex);
}
@Override
public int computeOutIndex(PLSQLargument outArg, int newIndex, ListIterator<PLSQLargument> i) {
return databaseTypeHelper.computeOutIndex(outArg, newIndex);
}
@Override
public void logParameter(StringBuilder sb, Integer direction, PLSQLargument arg,
AbstractRecord translationRow, DatabasePlatform platform) {
databaseTypeHelper.logParameter(sb, direction, arg, translationRow, platform);
}
@Override
public void translate(PLSQLargument arg, AbstractRecord translationRow,
AbstractRecord copyOfTranslationRow, List<DatabaseField> copyOfTranslationFields,
List<DatabaseField> translationRowFields, List translationRowValues, StoredProcedureCall call) {
databaseTypeHelper.translate(arg, translationRow, copyOfTranslationRow,
copyOfTranslationFields, translationRowFields, translationRowValues, call);
}
@Override
public String toString() {
return getClass().getSimpleName() + "(" + getTypeName() + ")";
}
}