blob: 7d3567af9f43de847f157f2d6b3a404ae0eab6f0 [file] [log] [blame]
/*
* 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.tuscany.das.rdb.impl;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.tuscany.das.rdb.config.ResultDescriptor;
import org.apache.tuscany.das.rdb.config.impl.ResultDescriptorImpl;
import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
import org.apache.tuscany.das.rdb.graphbuilder.impl.GraphBuilderMetadata;
import org.apache.tuscany.das.rdb.graphbuilder.impl.ResultSetProcessor;
import org.apache.tuscany.sdo.api.SDOUtil;
import commonj.sdo.ChangeSummary;
import commonj.sdo.DataGraph;
import commonj.sdo.DataObject;
public class ReadCommandImpl extends CommandImpl {
private int startRow = 1;
private int endRow = Integer.MAX_VALUE;
private List resultDescriptors = null;
public ReadCommandImpl(org.apache.tuscany.das.rdb.config.Command command, MappingWrapper mapping, List resultDescriptor) {
super(command);
this.configWrapper = mapping;
if (resultDescriptor != null && !resultDescriptor.isEmpty()) {
this.resultSetShape = new ResultSetShape(resultDescriptor, configWrapper.getConfig());//JIRA-952
}
}
public ReadCommandImpl(String sqlString, MappingWrapper mapping, List resultDescriptor) {
super(sqlString);
this.configWrapper = mapping;
if (resultDescriptor != null && !resultDescriptor.isEmpty()) {
this.resultSetShape = new ResultSetShape(resultDescriptor, configWrapper.getConfig());//JIRA-952
}
}
private void refreshResultSetShape(){
//sort descriptor and use in ResultSetShape
sortResultDescriptors();
this.resultSetShape = new ResultSetShape(this.resultDescriptors, configWrapper.getConfig());
}
private void sortResultDescriptors(){
if(this.resultDescriptors == null) {
return;
}
if( this.resultDescriptors.size()==0) {
return;
}
//when any index is found not set, do not sort
for(Iterator it = this.resultDescriptors.iterator() ; it.hasNext();){
ResultDescriptor resultDescriptor = (ResultDescriptor) it.next();
if(resultDescriptor.getColumnIndex() <= -1){
return;
}
}
//now is time to sort
Object[] resultDescAry = this.resultDescriptors.toArray();
for(int i=0; i<resultDescAry.length; i++){
for(int j=i+1; j<resultDescAry.length; j++){
if( ((ResultDescriptor)resultDescAry[j]).getColumnIndex()
< ((ResultDescriptor)resultDescAry[i]).getColumnIndex()){
ResultDescriptor tmpResDesc = (ResultDescriptor)resultDescAry[i];
resultDescAry[i] = resultDescAry[j];
resultDescAry[j] = tmpResDesc;
}
if( ((ResultDescriptor)resultDescAry[j]).getColumnIndex()
== ((ResultDescriptor)resultDescAry[i]).getColumnIndex()){
throw new RuntimeException("Two columns in Result Descriptor can not have same index");
}
}
}
this.resultDescriptors.clear();
for(int i=0; i<resultDescAry.length; i++){
this.resultDescriptors.add(resultDescAry[i]);
}
return;
}
private ResultDescriptor deepCopyResultDescriptor(ResultDescriptor inObj){
ResultDescriptorImpl outObj = new ResultDescriptorImpl();
outObj.setColumnIndex(inObj.getColumnIndex());
outObj.setColumnName(inObj.getColumnName());
outObj.setColumnType(inObj.getColumnType());
outObj.setTableName(inObj.getTableName());
outObj.setSchemaName(inObj.getSchemaName());
return outObj;
}
private List deepCopyResultDescriptors(List resultDescriptors){
if(resultDescriptors == null || resultDescriptors.size() == 0)
return null;
ArrayList copyList = new ArrayList();
for(Iterator it = resultDescriptors.iterator() ; it.hasNext();){
copyList.add( deepCopyResultDescriptor( (ResultDescriptorImpl) it.next()));
}
return copyList;
}
/**
* When any columnIndex == -ve, sorting will not happen in ResultShapeSorter (old way)
* When null is passed, set this.resultSetShape to null, this will later trigger, dbms metadata
* based shaping of result
*/
public void setResultDescriptors(List resultDescriptors){
this.resultDescriptors = deepCopyResultDescriptors(resultDescriptors);
if(this.resultDescriptors == null || this.resultDescriptors.size()==0){
this.resultSetShape = null;
}
else{
//below will go away with List<> JDK5
for(Iterator it = this.resultDescriptors.iterator() ; it.hasNext();){
if(!(it.next() instanceof ResultDescriptor)){
throw new RuntimeException("Elements in List not of type ResultDescriptor!");
}
}
refreshResultSetShape();
}
}
public List getResultDescriptors(){
return this.resultDescriptors;
}
public void addResultDescriptor(ResultDescriptor resultDescriptor){
//if >= 0 columnIndex, add/replace for given index
//if < 0 columnIndex, add at end of current list
if(resultDescriptor == null) {
return;
}
if(this.resultDescriptors == null){
this.resultDescriptors = new ArrayList();
}
if(resultDescriptor.getColumnIndex() <0){
this.resultDescriptors.add(deepCopyResultDescriptor(resultDescriptor));//dont care about columnIndex,add at end, old way
}
else{
ResultDescriptor existing = getResultDescriptor(resultDescriptor.getColumnIndex());
if(existing != null){
removeResultDescriptor(resultDescriptor.getColumnIndex());
}
this.resultDescriptors.add(deepCopyResultDescriptor(resultDescriptor));//add at end, sorting will happen below
}
refreshResultSetShape();
}
public ResultDescriptor removeResultDescriptor(int columnIndex){
//if < 0 index return null
//if >=0 index and available at given index, remove and return same
//if >=0 index and not available at given index, return null
ResultDescriptor existing = null;
if(columnIndex >=0 && ((existing = getResultDescriptor(columnIndex)) != null) ){
this.resultDescriptors.remove(existing);
refreshResultSetShape();
return existing;
}
return null;
}
public ResultDescriptor removeResultDescriptor(ResultDescriptor resultDescriptor){
//remove and return only if matched for index, name, type, table name, schema name
//else return null
if(resultDescriptor != null){
ResultDescriptor existing = getResultDescriptor(resultDescriptor.getColumnIndex());
if(existing != null &&
existing.getColumnName().equals(resultDescriptor.getColumnName()) &&
existing.getColumnType().equals(resultDescriptor.getColumnType()) &&
existing.getTableName().equals(resultDescriptor.getTableName()) ) {
if(this.configWrapper.getConfig().isDatabaseSchemaNameSupported()){//multi schema support
if(resultDescriptor.getSchemaName() != null && existing.getSchemaName() != null
&& resultDescriptor.getSchemaName().equals(existing.getSchemaName())){
this.resultDescriptors.remove(existing);
refreshResultSetShape();
return existing;
}
return null;
}
else{
this.resultDescriptors.remove(existing);
refreshResultSetShape();
return existing;
}
}
}
return null;
}
public ResultDescriptor getResultDescriptor(int columnIndex){
//if <0 index return null
//if >=0 index and available at given index, return same
//if >=0 index and not available at given index, return null
if(columnIndex >=0 && this.resultDescriptors != null){
for(Iterator it = this.resultDescriptors.iterator() ; it.hasNext();){
ResultDescriptor rs = (ResultDescriptor) it.next();
if( rs.getColumnIndex() == columnIndex){
return rs;
}
}
}
return null;
}
//Utility method
public void printResultDescriptors(OutputStream ostrm) throws IOException{
if(this.resultDescriptors != null && this.resultDescriptors.size() != 0){
for(Iterator it = this.resultDescriptors.iterator() ; it.hasNext();){
ostrm.write( it.next().toString().getBytes() );
ostrm.write('\n');
}
ostrm.flush();
}
}
public void execute() {
throw new UnsupportedOperationException();
}
public DataObject executeQuery() {
if (statement.getConnection() == null) {
throw new RuntimeException("A DASConnection object must be specified before executing the query.");
}
boolean success = false;
try {
// execute query
List results = statement.executeQuery(parameters);
success = true;
// if result set contains less columns than result descriptors, crop result descriptors
if (resultDescriptors != null && results.size() > 0) {
ResultSet resultSet = (ResultSet) results.get(0);
ResultSetMetaData resultSetMetadata = resultSet.getMetaData();
int columnCount = resultSetMetadata.getColumnCount();
int resultDescriptorCount = resultDescriptors.size();
if (resultDescriptorCount > columnCount) {
resultDescriptors = resultDescriptors.subList(0, columnCount);
refreshResultSetShape();
}
}
// build graph
return buildGraph(results);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
if (success) {
statement.getConnection().cleanUp();
} else {
statement.getConnection().errorCleanUp();
}
}
}
protected DataObject buildGraph(List results) throws SQLException {
// Before we use the mappingModel, do some checking/updating. If
// inferrable information
// isn't specified, add it in.
GraphBuilderMetadata gbmd = new GraphBuilderMetadata(results, configWrapper.getConfig(),
resultSetShape);
// Create the DataGraph
DataGraph g = SDOUtil.createDataGraph();
// Create the root object
g.createRootObject(gbmd.getRootType());
SDOUtil.registerDataGraphTypes(g, gbmd.getDefinedTypes());
ChangeSummary summary = g.getChangeSummary();
ResultSetProcessor rsp = new ResultSetProcessor(g.getRootObject(), gbmd);
rsp.processResults(getStartRow(), getEndRow());
summary.beginLogging();
return g.getRootObject();
}
protected int getStartRow() {
return startRow;
}
protected int getEndRow() {
return endRow;
}
protected void setStartRow(int startRow) {
this.startRow = startRow;
}
protected void setEndRow(int endRow) {
this.endRow = endRow;
}
protected void enablePaging() {
statement.enablePaging();
}
}