package org.eclipse.persistence.tools.workbench.mappingsmodel.query; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.eclipse.persistence.descriptors.InheritancePolicy; import org.eclipse.persistence.exceptions.ConversionException; import org.eclipse.persistence.internal.helper.ConversionManager; import org.eclipse.persistence.oxm.XMLDescriptor; import org.eclipse.persistence.oxm.mappings.XMLDirectMapping; import org.eclipse.persistence.tools.workbench.mappingsmodel.MWModel; import org.eclipse.persistence.tools.workbench.utility.ClassTools; import org.eclipse.persistence.tools.workbench.utility.CollectionTools; /** * @version 1.1 * @since 1.1 * @author Les Davis */ @SuppressWarnings("nls") public abstract class MWAbstractProcedureArgument extends MWModel { private static HashMap<String, Integer> jdbcTypes; public static final String JDBC_TYPES_PROPERTY = "jdbcTypes"; private static HashMap<Integer, String> jdbcTypesCodes; private String passType; public static final String PASS_TYPE_PROPERTY = "passType"; public static final String PARAMETER_TYPE = "paramter type"; public static final String VALUE_TYPE = "value type"; //limited to values convertible by TopLink runtime DTF private String argumentValue; public static final String ARGUMENT_VALUE_PROPERTY = "argumentValue"; private String argumentName; public static final String ARGUMENT_NAME_PROPERTY = "argumentName"; private String fieldName; public static final String FIELD_NAME_PROPERTY = "fieldName"; private String fieldSqlTypeName; public static final String FIELD_SQL_TYPE_PROPERTY = "fieldSqlType"; private String fieldSqlSubTypeName; public static final String FIELD_SQL_TYPE_NAME_PROPERTY = "fieldSqlSubTypeName"; private String fieldJavaClassName; public static final String FIELD_JAVA_CLASS_NAME_PROPERTY = "fieldJavaClassName"; private String nestedTypeFieldName; public static final String NESTED_TYPE_FIELD_NAME_PROPERTY = "nestedTypeFieldName"; //not persisted private transient ConversionManager conversionManager; /** * Default constructor for TopLink use only */ protected MWAbstractProcedureArgument() { super(); } MWAbstractProcedureArgument(MWProcedure procedure, String name) { super(procedure); this.argumentName = name; } @Override protected void initialize() { super.initialize(); this.passType = PARAMETER_TYPE; } /** * Returns <code>true</code> for named stored procedure, <code>false</code> * for un-named */ abstract boolean isNamed(); public abstract boolean isNamedIn(); public abstract boolean isNamedOut(); public abstract boolean isNamedInOut(); public abstract boolean isUnnamedIn(); public abstract boolean isUnnamedOut(); public abstract boolean isUnnamedInOut(); public static XMLDescriptor buildDescriptor() { XMLDescriptor descriptor = new XMLDescriptor(); descriptor.setJavaClass(MWAbstractProcedureArgument.class); InheritancePolicy ipolicy = descriptor.getInheritancePolicy(); ipolicy.setClassIndicatorFieldName("@type"); ipolicy.addClassIndicator(MWProcedureNamedInArgument.class, "procedure-named-argument"); ipolicy.addClassIndicator(MWProcedureUnamedInArgument.class, "procedure-unamed-argument"); ipolicy.addClassIndicator(MWProcedureNamedOutputArgument.class, "procedure-named-output-argument"); ipolicy.addClassIndicator(MWProcedureUnamedOutputArgument.class, "procedure-unamed-output-argument"); ipolicy.addClassIndicator(MWProcedureNamedInOutputArgument.class, "procedure-named-inoutput-argument"); ipolicy.addClassIndicator(MWProcedureUnamedInOutputArgument.class, "procedure-unamed-inoutput-argument"); XMLDirectMapping passTypeMapping = new XMLDirectMapping(); passTypeMapping.setAttributeName("passType"); passTypeMapping.setGetMethodName("getPassTypeForTopLink"); passTypeMapping.setSetMethodName("setPassTypeForTopLink"); passTypeMapping.setXPath("pass-type/text()"); descriptor.addMapping(passTypeMapping); XMLDirectMapping valueMapping = new XMLDirectMapping(); valueMapping.setAttributeName("argumentValue"); valueMapping.setGetMethodName("getArgumentValueForTopLink"); valueMapping.setSetMethodName("setArgumentValueForTopLink"); valueMapping.setXPath("argument-value/text()"); descriptor.addMapping(valueMapping); XMLDirectMapping argumentNameMapping = new XMLDirectMapping(); argumentNameMapping.setAttributeName("argumentName"); argumentNameMapping.setGetMethodName("getArgumentNameForTopLink"); argumentNameMapping.setSetMethodName("setArgumentNameForTopLink"); argumentNameMapping.setXPath("argument-name/text()"); descriptor.addMapping(argumentNameMapping); XMLDirectMapping fieldNameMapping = new XMLDirectMapping(); fieldNameMapping.setAttributeName("fieldName"); fieldNameMapping.setGetMethodName("getFieldNameForTopLink"); fieldNameMapping.setSetMethodName("setFieldNameForTopLink"); fieldNameMapping.setXPath("field-name/text()"); descriptor.addMapping(fieldNameMapping); descriptor.addDirectMapping("fieldSqlType", "getFieldSqlTypeNameForTopLink", "setFieldSqlTypeNameForTopLink", "field-sql-type/text()"); descriptor.addDirectMapping("fieldSqlTypeName", "getFieldSubTypeNameForTopLink", "setFieldTypeSubNameForTopLink", "field-sql-type-name/text()"); descriptor.addDirectMapping("fieldJavaClassName", "getFieldJavaClassNameForTopLink", "setFieldJavaClassNameForTopLink", "field-java-class-name/text()"); descriptor.addDirectMapping("nestedTypeFieldName", "getNestedTypeFieldNameForTopLink", "setNestedTypeFieldNameForTopLink", "nested-type-field-name/text()"); return descriptor; } public String getPassType() { return this.passType; } public void setPassType(String newValue) { String oldValue = this.passType; this.passType = newValue; firePropertyChanged(PASS_TYPE_PROPERTY, oldValue, newValue); } @SuppressWarnings("unused") private String getPassTypeForTopLink() { return this.passType; } @SuppressWarnings("unused") private void setPassTypeForTopLink(String newValue) { this.passType = newValue; } public String getArgumentValue() { return this.argumentValue; } //limited to values convertible by TopLink runtime public void setArgumentValue(String newValue) { Object oldValue = this.argumentValue; this.argumentValue = newValue; firePropertyChanged(ARGUMENT_VALUE_PROPERTY, oldValue, newValue); } @SuppressWarnings("unused") private String getArgumentValueForTopLink() { return this.argumentValue; } @SuppressWarnings("unused") private void setArgumentValueForTopLink(String newValue) { this.argumentValue = newValue; } /** * Convert the string to an object of the specified class. * If there are any problems, do nothing - the value will not be built. */ public Object buildValueFromString(String valueTypeName, String valueString) { try { Class<?> javaClass = ClassTools.classForTypeDeclaration(valueTypeName, 0); return this.getConversionManager().convertObject(valueString, javaClass); } catch (ClassNotFoundException ex) { // it's very unlikely this will happen since // we try to restrict the class to common classes (e.g. String, Date) } throw ConversionException.couldNotBeConverted(valueString, null); } private ConversionManager getConversionManager() { if (this.conversionManager == null) { this.conversionManager = new ConversionManager(); } return this.conversionManager; } public String getArgumentName(){ if (this.argumentName == null) { return ""; } else { return this.argumentName; } } public void setArgumentName(String argumentName){ String oldName = this.argumentName; this.argumentName = argumentName; firePropertyChanged(ARGUMENT_NAME_PROPERTY, oldName, argumentName); } @SuppressWarnings("unused") private void setArgumentNameForTopLink(String argumentName){ this.argumentName = argumentName; } @SuppressWarnings("unused") private String getArgumentNameForTopLink(){ return this.argumentName; } public String getFieldName(){ if (this.fieldName == null) { return ""; } else { return this.fieldName; } } public void setFieldName(String fieldName){ String oldName = this.fieldName; this.fieldName = fieldName; this.firePropertyChanged(FIELD_NAME_PROPERTY,oldName, this.fieldName); } @SuppressWarnings("unused") private void setFieldNameForTopLink(String fieldName){ this.fieldName = fieldName; } @SuppressWarnings("unused") private String getFieldNameForTopLink(){ return this.fieldName; } public int getFieldSqlTypeCode() { if (this.fieldSqlTypeName == null) { return -1; } return MWAbstractProcedureArgument.jdbcTypeCodeFor(this.fieldSqlTypeName); } public String getFieldSqlTypeName() { if (fieldSqlTypeName == null) { return ""; } return fieldSqlTypeName; } public void setFieldSqlTypeName(String fieldSqlTypeName) { String old = this.fieldSqlTypeName; this.fieldSqlTypeName = fieldSqlTypeName; this.firePropertyChanged(FIELD_SQL_TYPE_PROPERTY, old, this.fieldSqlTypeName); } private String getFieldSqlTypeNameForTopLink() { return this.fieldSqlTypeName; } private void setFieldSqlTypeNameForTopLink(String fieldSqlType) { this.fieldSqlTypeName = fieldSqlType; } public String getFieldSubTypeName() { if (this.fieldSqlSubTypeName == null) { return ""; } else { return fieldSqlSubTypeName; } } public void setFieldSubTypeName(String fieldTypeName) { String old = this.fieldSqlSubTypeName; this.fieldSqlSubTypeName = fieldTypeName; this.firePropertyChanged(FIELD_SQL_TYPE_NAME_PROPERTY, old, this.fieldSqlSubTypeName); } private String getFieldSubTypeNameForTopLink() { return this.fieldSqlSubTypeName; } private void setFieldTypeSubNameForTopLink(String newValue) { this.fieldSqlSubTypeName = newValue; } public String getFieldJavaClassName() { if (this.fieldJavaClassName == null) { return ""; } else { return fieldJavaClassName; } } public void setFieldJavaClassName(String fieldJavaClassName) { String old = this.fieldJavaClassName; this.fieldJavaClassName = fieldJavaClassName; this.firePropertyChanged(FIELD_JAVA_CLASS_NAME_PROPERTY, old, this.fieldJavaClassName); } private String getFieldJavaClassNameForTopLink() { return this.fieldJavaClassName; } private void setFieldJavaClassNameForTopLink(String newValue) { this.fieldJavaClassName = newValue; } public String getNestedTypeFieldName() { if (this.nestedTypeFieldName == null) { return ""; } else { return nestedTypeFieldName; } } public void setNestedTypeFieldName(String nestedTypeFieldName) { String old = this.nestedTypeFieldName; this.nestedTypeFieldName = nestedTypeFieldName; this.firePropertyChanged(NESTED_TYPE_FIELD_NAME_PROPERTY, old, this.nestedTypeFieldName); } private String getNestedTypeFieldNameForTopLink() { return this.nestedTypeFieldName; } private void setNestedTypeFieldNameForTopLink(String newValue) { this.nestedTypeFieldName = newValue; } public MWProcedure getProcedure() { return (MWProcedure)getParent(); } public MWQuery getQuery() { return getProcedure().getQuery(); } public ListIterator<String> getQueryParameterNames() { return CollectionTools.listIterator(getQuery().parameterNames()); } public static int jdbcTypesSize() { return jdbcTypes().size(); } public static Iterator<String> jdbcTypeNames() { return jdbcTypes().keySet().iterator(); } public static int jdbcTypeCodeFor(String name) { return jdbcTypes().get(name).intValue(); } public static String jdbcTypeNameFor(int value) { return jdbcTypeCodes().get(new Integer(value)); } public static HashMap<Integer, String> jdbcTypeCodes() { if (jdbcTypesCodes == null) { jdbcTypesCodes = new HashMap<Integer, String>(); jdbcTypesCodes.put(new Integer(2003), "ARRAY"); jdbcTypesCodes.put(new Integer(-5), "BIGINT"); jdbcTypesCodes.put(new Integer(-2), "BINARY"); jdbcTypesCodes.put(new Integer(-7), "BIT"); jdbcTypesCodes.put(new Integer(2004), "BLOB"); jdbcTypesCodes.put(new Integer(16), "BOOLEAN"); jdbcTypesCodes.put(new Integer(1), "CHAR"); jdbcTypesCodes.put(new Integer(2005), "CLOB"); jdbcTypesCodes.put(new Integer(70), "DATALINK"); jdbcTypesCodes.put(new Integer(91), "DATE"); jdbcTypesCodes.put(new Integer(3), "DECIMAL"); jdbcTypesCodes.put(new Integer(2001), "DISTINCT"); jdbcTypesCodes.put(new Integer(8), "DOUBLE"); jdbcTypesCodes.put(new Integer(6), "FLOAT"); jdbcTypesCodes.put(new Integer(4), "INTEGER"); jdbcTypesCodes.put(new Integer(2000), "JAVA OBJECT"); jdbcTypesCodes.put(new Integer(-4), "LONGVARBINARY"); jdbcTypesCodes.put(new Integer(-1), "LONGVARCHAR"); jdbcTypesCodes.put(new Integer(0), "NULL"); jdbcTypesCodes.put(new Integer(2), "NUMERIC"); jdbcTypesCodes.put(new Integer(1111), "OTHER"); jdbcTypesCodes.put(new Integer(7), "REAL"); jdbcTypesCodes.put(new Integer(2006), "REF"); jdbcTypesCodes.put(new Integer(5), "SMALLINT"); jdbcTypesCodes.put(new Integer(2002), "STRUCT"); jdbcTypesCodes.put(new Integer(92), "TIME"); jdbcTypesCodes.put(new Integer(93), "TIMESTAMP"); jdbcTypesCodes.put(new Integer(-6), "TINYINT"); jdbcTypesCodes.put(new Integer(-3), "VARBINARY"); jdbcTypesCodes.put(new Integer(12), "VARCHAR"); } return jdbcTypesCodes; } private static HashMap<String, Integer> jdbcTypes() { if (jdbcTypes == null) { jdbcTypes = new HashMap<String, Integer>(); jdbcTypes.put("ARRAY", new Integer(2003)); jdbcTypes.put("BIGINT", new Integer(-5)); jdbcTypes.put("BINARY", new Integer(-2)); jdbcTypes.put("BIT", new Integer(-7)); jdbcTypes.put("BLOB", new Integer(2004)); jdbcTypes.put("BOOLEAN", new Integer(16)); jdbcTypes.put("CHAR", new Integer(1)); jdbcTypes.put("CLOB", new Integer(2005)); jdbcTypes.put("DATALINK", new Integer(70)); jdbcTypes.put("DATE", new Integer(91)); jdbcTypes.put("DECIMAL", new Integer(3)); jdbcTypes.put("DISTINCT", new Integer(2001)); jdbcTypes.put("DOUBLE", new Integer(8)); jdbcTypes.put("FLOAT", new Integer(6)); jdbcTypes.put("INTEGER", new Integer(4)); jdbcTypes.put("JAVA OBJECT", new Integer(2000)); jdbcTypes.put("LONGVARBINARY", new Integer(-4)); jdbcTypes.put("LONGVARCHAR", new Integer(-1)); jdbcTypes.put("NULL", new Integer(0)); jdbcTypes.put("NUMERIC", new Integer(2)); jdbcTypes.put("OTHER", new Integer(1111)); jdbcTypes.put("REAL", new Integer(7)); jdbcTypes.put("REF", new Integer(2006)); jdbcTypes.put("SMALLINT", new Integer(5)); jdbcTypes.put("STRUCT", new Integer(2002)); jdbcTypes.put("TIME", new Integer(92)); jdbcTypes.put("TIMESTAMP", new Integer(93)); jdbcTypes.put("TINYINT", new Integer(-6)); jdbcTypes.put("VARBINARY", new Integer(-3)); jdbcTypes.put("VARCHAR", new Integer(12)); } return jdbcTypes; } public static List<String> buildBasicTypesList() { List<String> list = new ArrayList<String>(); list.add("java.lang.Boolean"); list.add("java.lang.Byte"); list.add("java.lang.Character"); list.add("java.lang.Double"); list.add("java.lang.Float"); list.add("java.lang.Integer"); list.add("java.lang.Long"); list.add("java.lang.Short"); list.add("java.lang.String"); list.add("java.math.BigDecimal"); list.add("java.math.BigInteger"); list.add("java.sql.Date"); list.add("java.sql.Time"); list.add("java.sql.Timestamp"); list.add("java.util.Calendar"); list.add("java.util.Date"); list.add("java.sql.Blob"); list.add("java.sql.Clob"); return list; } }