/*
* Copyright 2005 Assaf Arkin, Thomas Yip, Bruce Snyder, Werner Guttmann, Ralf Joachim
*
* Licensed 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.
*
* $Id$
*/
package org.exolab.castor.jdo.engine;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.castor.jdo.engine.SQLTypeInfos;
import org.exolab.castor.jdo.engine.nature.ClassDescriptorJDONature;
import org.exolab.castor.jdo.engine.nature.FieldDescriptorJDONature;
import org.exolab.castor.mapping.ClassDescriptor;
import org.exolab.castor.mapping.FieldDescriptor;
import org.exolab.castor.mapping.loader.ClassDescriptorImpl;
import org.exolab.castor.persist.spi.Identity;
/**
* @author <a href="mailto:arkin AT intalio DOT com">Assaf Arkin</a>
* @author <a href="mailto:yip AT intalio DOT com">Thomas Yip</a>
* @author <a href="mailto:ferret AT frii DOT com">Bruce Snyder</a>
* @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
* @author <a href="mailto:ralf DOT joachim AT syscon DOT eu">Ralf Joachim</a>
* @version $Revision$ $Date: 2006-04-13 06:47:36 -0600 (Thu, 13 Apr 2006) $
* @since 1.0
*/
public final class SQLHelper {
/** The <a href="http://jakarta.apache.org/commons/logging/">Jakarta
* Commons Logging</a> instance used for all logging. */
private static final Log LOG = LogFactory.getLog(SQLQuery.class);
public static Object[] calculateNumberOfFields(
final Collection<ClassDescriptor> extendingClassDescriptors,
final int numberOfIdentityColumns, final int numberOfFields,
final int numberOfExtendLevels, final ResultSet rs) throws SQLException {
ClassDescriptor potentialLeafDescriptor = null;
int suggestedNumberOfFields = numberOfFields;
Collection<ClassDescriptor> potentialCDRs = new LinkedList<ClassDescriptor>();
int numberOfIdentitiesToAnalyze = 0;
addExtendingClassDescriptors(potentialCDRs, extendingClassDescriptors);
ClassDescriptor potentialClassDescriptor = null;
ClassDescriptor potentialClassDescriptorPrevious = null;
int initialColumnIndex =
numberOfFields + numberOfIdentityColumns * numberOfExtendLevels + 1;
int columnIndex = initialColumnIndex;
int numberOfExtendingClassDescriptors = 0;
for (Iterator<ClassDescriptor> iter = potentialCDRs.iterator(); iter.hasNext(); ) {
potentialClassDescriptor = iter.next();
numberOfExtendingClassDescriptors += 1;
if (LOG.isDebugEnabled()) {
LOG.debug ("Potential extending class descriptor: "
+ potentialClassDescriptor.getJavaClass().getName());
}
ClassDescriptorImpl cdi = (ClassDescriptorImpl) potentialClassDescriptor;
FieldDescriptor[] identityDescriptors = cdi.getIdentities();
boolean isNull = true;
for (int i = 0; i < identityDescriptors.length; i++) {
Object temp;
final FieldDescriptorJDONature jdoFieldNature =
new FieldDescriptorJDONature(identityDescriptors[i]);
if (jdoFieldNature.getSQLName().length == 1) {
temp = SQLTypeInfos.getValue(rs, columnIndex++, java.sql.Types.JAVA_OBJECT);
} else {
Object[] temps = new Object[jdoFieldNature.getSQLName().length];
for (int j = 0; j < jdoFieldNature.getSQLName().length; j++) {
temps[j] = SQLTypeInfos.getValue(
rs, columnIndex++, java.sql.Types.JAVA_OBJECT);
}
temp = new Identity(temps);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Obtained value " + temp + " for additional (extending) identity "
+ potentialClassDescriptor.getJavaClass().getName() + "/"
+ identityDescriptors[i].getFieldName() + " at position "
+ columnIndex);
}
isNull = (temp == null);
if (!isNull) {
numberOfIdentitiesToAnalyze += 1;
potentialClassDescriptorPrevious = potentialClassDescriptor;
}
}
if (!iter.hasNext() && !isNull && numberOfIdentitiesToAnalyze > 0) {
potentialLeafDescriptor = potentialClassDescriptor;
suggestedNumberOfFields += potentialClassDescriptor.getFields().length;
} else if (!iter.hasNext() && isNull && numberOfIdentitiesToAnalyze > 0) {
potentialLeafDescriptor = potentialClassDescriptorPrevious;
// suggestedNumberOfFields += potentialClassDescriptor.getFields().length;
} else {
FieldDescriptor[] potentialFields =
potentialClassDescriptor.getFields();
for (int i = 0; i < potentialFields.length; i++) {
String[] columnNames =
new FieldDescriptorJDONature(potentialFields[i]).getSQLName();
if (columnNames != null) {
columnIndex = columnIndex + columnNames.length;
}
}
// the JDOClassDescriptor we just looked at is definitely part of the extends
// hierarchy, and as such we need to increase the number of potential fields
if (!isNull) {
suggestedNumberOfFields += potentialClassDescriptor.getFields().length;
}
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("In total " + numberOfIdentitiesToAnalyze
+ " (extending) identities analyzed.");
if (potentialLeafDescriptor != null) {
LOG.debug("Most likely of type "
+ potentialLeafDescriptor.getJavaClass().getName());
LOG.debug("After analysis, " + suggestedNumberOfFields
+ " fields need to be loaded.");
}
}
return new Object[] {potentialLeafDescriptor, new Integer (suggestedNumberOfFields) };
}
public static int numberOfExtendingClassDescriptors(final ClassDescriptor classDescriptor) {
int numberOfExtendLevels = 1;
ClassDescriptor currentClassDescriptor = classDescriptor;
while (currentClassDescriptor.getExtends() != null) {
currentClassDescriptor = currentClassDescriptor.getExtends();
numberOfExtendLevels++;
}
return numberOfExtendLevels;
}
public static void addExtendingClassDescriptors(
final Collection<ClassDescriptor> classDescriptorsToAdd,
final Collection<ClassDescriptor> extendClassDescriptors) {
ClassDescriptor classDescriptor = null;
for (Iterator<ClassDescriptor> iter = extendClassDescriptors.iterator(); iter.hasNext(); ) {
classDescriptor = iter.next();
classDescriptorsToAdd.add(classDescriptor);
ClassDescriptorJDONature nature = new ClassDescriptorJDONature(classDescriptor);
addExtendingClassDescriptors(classDescriptorsToAdd, nature.getExtended());
}
}
public static String[] getIdentitySQLNames(final ClassDescriptor desc) {
FieldDescriptor[] identities = ((ClassDescriptorImpl) desc).getIdentities();
String[] sqlNames = new String[identities.length];
for (int i = 0; i < identities.length; i++) {
sqlNames[i] = new FieldDescriptorJDONature(identities[i]).getSQLName()[0];
}
return sqlNames;
}
private SQLHelper() { }
}