/** * INTERNAL: Build a row representation from the ADT structure field array. TopLink will then * build the object from the row. */ public AbstractRecord buildRowFromStructure(Struct structure) throws DatabaseException { Object[] attributes; try { attributes = structure.getAttributes(); } catch (java.sql.SQLException exception) { throw DatabaseException.sqlException(exception); } if (attributes != null) { for (int i = 0; i < attributes.length; i++) { if (attributes[i] instanceof Array) { attributes[i] = ObjectRelationalDataTypeDescriptor.buildArrayObjectFromArray(attributes[i]); } else if (attributes[i] instanceof Struct) { attributes[i] = ObjectRelationalDataTypeDescriptor.buildArrayObjectFromStruct(attributes[i]); } } } return buildNestedRowFromFieldValue(attributes); }
@SuppressWarnings({"unchecked" /*, "rawtypes"*/}) @Override public void beginPlsqlRecordField(String fieldName, int idx) { RecordHelper recordHelper = (RecordHelper) stac.peek(); ObjectRelationalDataTypeDescriptor ordt = descriptorMap.get(recordHelper.targetTypeName().toLowerCase()); String lFieldName = fieldName.toLowerCase(); 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().equals(lFieldName)) { found = true; break; } } } if (!found) { ordt.addFieldOrdering(lFieldName); } }
@Override public void endPlsqlTable(String tableName, String typeDDL, String typeDropDDL) { ListenerHelper top = stac.pop(); TableHelper tableHelper = (TableHelper) stac.peek(); String tableAlias = tableHelper.targetTypeName().toLowerCase(); ObjectRelationalDataTypeDescriptor ordt = descriptorMap.get(tableAlias); if (ordt == null) { ordt = new ObjectRelationalDataTypeDescriptor(); ordt.descriptorIsAggregate(); ordt.setAlias(tableHelper.tableAlias()); ordt.setJavaClassName(tableName.toLowerCase() + COLLECTION_WRAPPER_SUFFIX); ordt.getQueryManager(); } boolean itemsMappingFound = ordt.getMappingForAttributeName(ITEMS_MAPPING_ATTRIBUTE_NAME) == null ? false : true; if (top.isRecord()) { if (!itemsMappingFound) { ObjectArrayMapping itemsMapping = new ObjectArrayMapping(); itemsMapping.setAttributeName(ITEMS_MAPPING_ATTRIBUTE_NAME); itemsMapping.setFieldName(ITEMS_MAPPING_FIELD_NAME); itemsMapping.setStructureName(tableHelper.targetTypeName()); itemsMapping.setReferenceClassName(((RecordHelper) top).recordName().toLowerCase()); ordt.addMapping(itemsMapping); } tableHelper.nestedIsComplex(); } else { if (!itemsMappingFound) { ArrayMapping itemsMapping = new ArrayMapping(); itemsMapping.setAttributeName(ITEMS_MAPPING_ATTRIBUTE_NAME); itemsMapping.setFieldName(ITEMS_MAPPING_FIELD_NAME); itemsMapping.useCollectionClass(ArrayList.class); itemsMapping.setStructureName(tableHelper.targetTypeName()); ordt.addMapping(itemsMapping); } if (top.isTable()) { tableHelper.nestedIsComplex(); } } if (!itemsMappingFound) { descriptorMap.put(tableAlias, ordt); } }
@Override public void beginPlsqlRecord(String plsqlRecordName, String targetTypeName, int numFields) { RecordHelper recordHelper = new RecordHelper(plsqlRecordName, targetTypeName, numFields); stac.push(recordHelper); String recordAlias = targetTypeName.toLowerCase(); ObjectRelationalDataTypeDescriptor ordt = descriptorMap.get(recordAlias); if (ordt == null) { ordt = new ObjectRelationalDataTypeDescriptor(); ordt.descriptorIsAggregate(); ordt.setAlias(recordAlias); ordt.setJavaClassName(plsqlRecordName.toLowerCase()); ordt.getQueryManager(); ordt.setStructureName(targetTypeName); descriptorMap.put(recordAlias, ordt); } }
@Override public void endPlsqlRecordField(String fieldName, int idx) { ListenerHelper top = stac.pop(); ListenerHelper listenerHelper = stac.peek(); if (listenerHelper.isRecord()) { RecordHelper recordHelper = (RecordHelper) stac.peek(); ObjectRelationalDataTypeDescriptor ordt = descriptorMap.get(recordHelper.targetTypeName().toLowerCase()); String lFieldName = fieldName.toLowerCase(); if (ordt.getMappingForAttributeName(lFieldName) == null) { if (top.isComplex()) { if (top.isTable()) { if (((TableHelper) top).isNestedComplex()) { ObjectArrayMapping objectArrayMapping = new ObjectArrayMapping(); objectArrayMapping.setAttributeName(lFieldName); objectArrayMapping.setFieldName(lFieldName); objectArrayMapping.setStructureName(top.targetTypeName()); objectArrayMapping.setReferenceClassName( ((TableHelper) top).tableName().toLowerCase() + COLLECTION_WRAPPER_SUFFIX); ordt.addMapping(objectArrayMapping); } else { ArrayMapping arrayMapping = new ArrayMapping(); arrayMapping.setAttributeName(lFieldName); arrayMapping.setFieldName(lFieldName); arrayMapping.setStructureName(top.targetTypeName()); ordt.addMapping(arrayMapping); } } else if (top.isRecord()) { StructureMapping structureMapping = new StructureMapping(); structureMapping.setAttributeName(lFieldName); structureMapping.setFieldName(lFieldName); structureMapping.setReferenceClassName(((RecordHelper) top).recordName().toLowerCase()); ordt.addMapping(structureMapping); } } else { ordt.addDirectMapping(lFieldName, lFieldName); } } } else { System.identityHashCode(listenerHelper); } }
/** * INTERNAL: Build and return the nested rows from the specified field value. This method allows * the field value to be an ARRAY containing other structures such as arrays or Struct, or direct * values. */ public static Object buildContainerFromArray( Array fieldValue, ObjectRelationalDatabaseField arrayField, AbstractSession session) throws DatabaseException { if (arrayField.getType() == null) { return fieldValue; } Object[] objects = null; try { objects = (Object[]) fieldValue.getArray(); } catch (java.sql.SQLException ex) { throw DatabaseException.sqlException(ex, session, false); } if (objects == null) { return null; } boolean isNestedStructure = false; ObjectRelationalDataTypeDescriptor ord = null; DatabaseField nestedType = null; if (arrayField != null) { nestedType = arrayField.getNestedTypeField(); if ((nestedType != null) && nestedType.getSqlType() == Types.STRUCT) { ClassDescriptor descriptor = session.getDescriptor(nestedType.getType()); if ((descriptor != null) && (descriptor.isObjectRelationalDataTypeDescriptor())) { // this is used to convert non-null objects passed through stored procedures and custom // SQL to structs ord = (ObjectRelationalDataTypeDescriptor) descriptor; } } else if ((nestedType != null) && (nestedType instanceof ObjectRelationalDatabaseField)) { isNestedStructure = true; } } // handle ARRAY conversions ReadObjectQuery query = new ReadObjectQuery(); query.setSession(session); ContainerPolicy cp = ContainerPolicy.buildPolicyFor(arrayField.getType()); Object container = cp.containerInstance(objects.length); for (int i = 0; i < objects.length; i++) { Object arrayValue = objects[i]; if (arrayValue == null) { return null; } if (ord != null) { AbstractRecord nestedRow = ord.buildRowFromStructure((Struct) arrayValue); ClassDescriptor descriptor = ord; if (descriptor.hasInheritance()) { Class newElementClass = descriptor.getInheritancePolicy().classFromRow(nestedRow, session); if (!descriptor.getJavaClass().equals(newElementClass)) { descriptor = session.getDescriptor(newElementClass); if (descriptor == null) { descriptor = ord; } } } arrayValue = descriptor.getObjectBuilder().buildNewInstance(); descriptor .getObjectBuilder() .buildAttributesIntoObject(arrayValue, nestedRow, query, null, false); } else if (isNestedStructure && (arrayValue instanceof Array)) { arrayValue = buildContainerFromArray( (Array) arrayValue, (ObjectRelationalDatabaseField) nestedType, session); } cp.addInto(arrayValue, container, session); } return container; }