/*****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
****************************************************************/
package org.apache.cayenne.access.jdbc.reader;
import java.sql.ResultSet;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.DataRow;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.jdbc.RowDescriptor;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.query.EntityResultSegment;
import org.apache.cayenne.query.QueryMetadata;
import org.apache.cayenne.util.Util;
/**
* @since 3.0
*/
class IdRowReader<T> extends BaseRowReader<T> {
protected int[] pkIndices;
public IdRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, EntityResultSegment resultMetadata, DataRowPostProcessor postProcessor) {
super(descriptor, queryMetadata, postProcessor);
DbEntity dbEntity = resultMetadata == null
? queryMetadata.getDbEntity()
: resultMetadata.getClassDescriptor().getEntity().getDbEntity();
if (dbEntity == null) {
throw new CayenneRuntimeException("Null root DbEntity, can't index PK");
}
int len = dbEntity.getPrimaryKeys().size();
// sanity check
if (len == 0) {
throw new CayenneRuntimeException("Root DBEntity has no PK defined: %s", dbEntity);
}
int[] pk = new int[len];
ColumnDescriptor[] columns = descriptor.getColumns();
for (int i = 0, j = 0; i < columns.length; i++) {
DbAttribute a = dbEntity.getAttribute(columns[i].getName());
if (a != null && a.isPrimaryKey()) {
pk[j++] = i;
}
}
this.pkIndices = pk;
}
@Override
public T readRow(ResultSet resultSet) {
try {
if (pkIndices.length == 1) {
return readSingleId(resultSet);
} else {
return readIdMap(resultSet);
}
} catch (CayenneRuntimeException cex) {
// rethrow unmodified
throw cex;
} catch (Exception otherex) {
throw new CayenneRuntimeException("Exception materializing id column.", Util.unwindException(otherex));
}
}
private T readSingleId(ResultSet resultSet) throws Exception {
// dereference column index
int index = pkIndices[0];
// note: jdbc column indexes start from 1, not 0 as in arrays
@SuppressWarnings("unchecked")
T val = (T) converters[index].materializeObject(resultSet, index + 1, types[index]);
// note that postProcessor overrides are not applied. ID mapping must be
// the
// same across inheritance hierarchy, so overrides do not make sense.
return val;
}
@SuppressWarnings("unchecked")
private T readIdMap(ResultSet resultSet) throws Exception {
DataRow idRow = new DataRow(2);
idRow.setEntityName(entityName);
for (int index : pkIndices) {
// dereference column index
// note: jdbc column indexes start from 1, not 0 as in arrays
Object val = converters[index].materializeObject(resultSet, index + 1, types[index]);
idRow.put(labels[index], val);
}
if (postProcessor != null) {
postProcessor.postprocessRow(resultSet, idRow);
}
return (T) idRow;
}
}