summaryrefslogtreecommitdiffstats
path: root/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org')
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Command.java138
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/ConfigHelper.java287
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Converter.java54
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/DAS.java67
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/DASFactory.java74
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Pager.java64
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java738
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/QualifiedColumn.java94
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/RelationshipWrapper.java47
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/TableWrapper.java149
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/exception/DataSourceInitializationException.java36
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/exception/OptimisticConcurrencyException.java31
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/BaseGenerator.java36
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/DeleteGenerator.java91
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/InsertGenerator.java182
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/UpdateGenerator.java228
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DataObjectMaker.java120
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DefaultConverter.java84
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/GraphBuilderMetadata.java279
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java104
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultMetadata.java401
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetProcessor.java154
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetRow.java264
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/RowObjects.java145
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java46
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableData.java102
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java45
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/schema/ResultSetTypeMap.java137
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java79
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java62
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java177
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java87
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java241
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java82
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CollisionParameter.java31
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java178
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java154
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java30
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java50
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java313
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java202
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java37
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java77
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java38
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java57
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java75
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java95
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java39
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java48
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java69
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterExtendedImpl.java98
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java120
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java113
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParametersExtendedImpl.java189
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java338
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java161
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java187
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java131
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java100
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java233
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java37
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java45
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java32
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java165
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java228
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/CollectionsUtil.java49
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/ConfigUtil.java130
-rw-r--r--das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DataObjectUtil.java79
68 files changed, 8853 insertions, 0 deletions
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Command.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Command.java
new file mode 100644
index 0000000000..1e641b71e7
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Command.java
@@ -0,0 +1,138 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import org.apache.tuscany.das.rdb.config.ResultDescriptor;
+
+import commonj.sdo.DataObject;
+
+/**
+ * A Command is used to execute a read or write to a database
+ */
+public interface Command {
+
+ /**
+ * Performs the function defined by the command
+ */
+ void execute();
+
+ /**
+ * Performs the function defined by the command and return the results in the root DataObject
+ *
+ * @return the root DataObject
+ */
+ DataObject executeQuery();
+
+ /**
+ * Sets the value of the associated Parameter
+ *
+ * @param index
+ * the index of the Parameter
+ * @param value
+ * the value for the Parameter
+ */
+ void setParameter(int index, Object value);
+
+ /**
+ * Returns the value of the associated Parameter
+ *
+ * @param index
+ * the index of the Parameter
+ * @return the value of the Parameter
+ */
+ Object getParameter(int index);
+
+ /**
+ *
+ * @param name Name of parameter - should match exact name of database table column
+ * as appearing in Command
+ * @param value
+ * the value of the parameter
+ */
+ void setParameter(String name, Object value);
+
+ /**
+ *
+ * @param name
+ * the name of the parameter - should match exact name of database table column
+ * @return the value of the parameter
+ */
+ Object getParameter(String name);
+
+ /**
+ * Returns the value of the database-generated key. This method is specific
+ * to an "insert" command and will be valid only after the command has
+ * been executed.
+ *
+ * @return the generated key
+ */
+ int getGeneratedKey();
+
+ /**
+ * Allow set of ResultDescriptor when command is created on-the-fly
+ * @param resultDescriptorList
+ */
+ void setResultDescriptors(List resultDescriptorList);
+
+ List getResultDescriptors();
+
+ /**
+ * Add/replace based on columnIndex (>=0)embedded in resultDescriptor else add at end
+ * @param resultDescriptor
+ */
+ void addResultDescriptor(ResultDescriptor resultDescriptor);
+
+ /**
+ * remove ResultDescriptor at given columnIndex(>=0) and return same. If not
+ * present return null. For -ve index, return null
+ * @param columnIndex
+ * @return
+ */
+ ResultDescriptor removeResultDescriptor(int columnIndex);
+
+ /**
+ * Remove resultDescriptor only if matched for index(>=0), name, type, schema
+ * name and table name and return same, else return null For -ve index, ignore
+ * index and if unique match for rest of the attriutes, remove/return, if multiple
+ * matches found, throw RuntimeException
+ * @param resultDescriptor
+ * @return
+ */
+ ResultDescriptor removeResultDescriptor(ResultDescriptor resultDescriptor);
+
+ /**
+ * Return resultDescriptor if exact match for columnIndex(>=0) found
+ * else return null;
+ *
+ * @param columnIndex
+ * @return
+ */
+ ResultDescriptor getResultDescriptor(int columnIndex);
+
+ /**
+ * Utility method
+ * @param ostrm
+ * @throws IOException
+ */
+ void printResultDescriptors(OutputStream ostrm) throws IOException;
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/ConfigHelper.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/ConfigHelper.java
new file mode 100644
index 0000000000..431705b7e6
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/ConfigHelper.java
@@ -0,0 +1,287 @@
+/*
+ * 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;
+
+import java.io.InputStream;
+import java.util.Vector;
+
+import org.apache.tuscany.das.rdb.config.Column;
+import org.apache.tuscany.das.rdb.config.Command;
+import org.apache.tuscany.das.rdb.config.Config;
+import org.apache.tuscany.das.rdb.config.ConfigFactory;
+import org.apache.tuscany.das.rdb.config.Parameters;
+import org.apache.tuscany.das.rdb.config.Relationship;
+import org.apache.tuscany.das.rdb.config.Table;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+import org.apache.tuscany.das.rdb.util.ConfigUtil;
+import org.apache.tuscany.das.rdb.impl.ParametersExtendedImpl;
+
+/**
+ * A ConfigHelper is used as an aid in programmatic construction of Config instances.
+ * Manual contrution fo COnfig is an alternative to providing needed configuration
+ * information in an XML file
+ *
+ */
+public class ConfigHelper {
+
+ private Config config;
+
+ private MappingWrapper configWrapper;
+
+ private ConfigFactory factory = ConfigFactory.INSTANCE;
+
+ /**
+ * Default constructor
+ */
+ public ConfigHelper() {
+ config = factory.createConfig();
+ configWrapper = new MappingWrapper(config);
+ }
+
+ /**
+ * Constructor that receives a Config stream
+ * This is usefull to extend a config file
+ * @param configStream The configuration stream
+ */
+ public ConfigHelper(InputStream configStream) {
+ this.config = ConfigUtil.loadConfig(configStream);
+ configWrapper = new MappingWrapper(config);
+ }
+
+ /**
+ * Constructor that receives a Config object
+ * @param config The configuration object
+ */
+ public ConfigHelper(Config config) {
+ this.config = config;
+ configWrapper = new MappingWrapper(config);
+ }
+
+ /**
+ * Add PK information
+ * @param columnName The column to be taken as PK
+ */
+ public void addPrimaryKey(String columnName) {
+ configWrapper.addPrimaryKey(columnName);
+ }
+
+ /**
+ * Add relationship information
+ * @param parentName
+ * @param childName
+ * @return
+ */
+ public Relationship addRelationship(String parentName, String childName) {
+ return configWrapper.addRelationship(parentName, childName);
+ }
+
+ /**
+ * Add relationship information
+ * @param parentNames
+ * @param childNames
+ * @return
+ */
+ public Relationship addRelationship(Vector parentNames, Vector childNames) {
+ return configWrapper.addRelationship(parentNames, childNames);
+ }
+
+ /**
+ * Add table information
+ * @param name
+ * @param typeName
+ * @return
+ */
+ public Table addTable(String name, String typeName) {
+ return configWrapper.addTable(name, typeName);
+ }
+
+ /**
+ * Add table information with schema information
+ * @param name
+ * @param schemaName
+ * @param typeName
+ * @return
+ */
+ public Table addTable(String name, String schemaName, String typeName) {
+ return configWrapper.addTable(name, schemaName, typeName);
+ }
+
+ /**
+ * Add column information
+ * @param table
+ * @param columnName
+ * @param propertyName
+ * @return
+ */
+ public Column addColumn(Table table, String columnName, String propertyName) {
+ return configWrapper.addColumn(table, columnName, propertyName);
+ }
+
+ /**
+ * Add an update statement for a given table
+ * @param table
+ * @param statement
+ * @param parameters String - names separated with space
+ */
+ public void addUpdateStatement(Table table, String statement, String parameters) {
+ ParametersExtendedImpl parametersExtendedImpl = new ParametersExtendedImpl();
+ parametersExtendedImpl.addParameters(ParametersExtendedImpl.getParameters(parameters));
+ configWrapper.addUpdateStatement(table, statement, parametersExtendedImpl);
+ }
+
+ /**
+ * Add an update statement for a given table
+ * @param table
+ * @param statement
+ * @param parameters <Parameters>
+ */
+ public void addUpdateStatement(Table table, String statement, Parameters parameters) {
+ configWrapper.addUpdateStatement(table, statement, parameters);
+ }
+
+ /**
+ * Add create statement for a given table
+ * @param table
+ * @param statement
+ * @param parameters String - names separated with space
+ */
+ public void addCreateStatement(Table table, String statement, String parameters) {
+ ParametersExtendedImpl parametersExtendedImpl = new ParametersExtendedImpl();
+ parametersExtendedImpl.addParameters(ParametersExtendedImpl.getParameters(parameters));
+ configWrapper.addCreateStatement(table, statement, parametersExtendedImpl);
+ }
+
+ /**
+ * Add create statement for a given table
+ * @param table
+ * @param statement
+ * @param parameters <Parameters>
+ */
+ public void addCreateStatement(Table table, String statement, Parameters parameters) {
+ configWrapper.addCreateStatement(table, statement, parameters);
+ }
+
+ /**
+ * Add delete statement for a given table
+ * @param table
+ * @param statement
+ * @param parameters String - names separated with space
+ */
+ public void addDeleteStatement(Table table, String statement, String parameters) {
+ ParametersExtendedImpl parametersExtendedImpl = new ParametersExtendedImpl();
+ parametersExtendedImpl.addParameters(ParametersExtendedImpl.getParameters(parameters));
+ configWrapper.addDeleteStatement(table, statement, parametersExtendedImpl);
+ }
+
+ /**
+ * Add delete statement for a given table
+ * @param table
+ * @param statement
+ * @param parameters <Parameters>
+ */
+ public void addDeleteStatement(Table table, String statement, Parameters parameters) {
+ configWrapper.addDeleteStatement(table, statement, parameters);
+ }
+
+ /**
+ * Add datasource connection information
+ * @param dataSourceName
+ */
+ public void addConnectionInfo(String dataSourceName) {
+ configWrapper.addConnectionInfo(dataSourceName, true);
+ }
+
+ /**
+ * Add datasource connection information and flag about using managed transactions
+ * @param dataSourceName
+ * @param managedtx
+ */
+ public void addConnectionInfo(String dataSourceName, boolean managedtx) {
+ configWrapper.addConnectionInfo(dataSourceName, managedtx);
+ }
+
+ /**
+ * Add driver manager connection information
+ * @param driverClass
+ * @param databaseURL
+ * @param user
+ * @param password
+ * @param loginTimeout
+ */
+ public void addConnectionInfo(String driverClass, String databaseURL, String user, String password, int loginTimeout) {
+ configWrapper.addConnectionInfo(driverClass, databaseURL, user, password, loginTimeout);
+ }
+
+ /**
+ * Set the data object model
+ * @param dataObjectModel
+ */
+ public void setDataObjectModel(String dataObjectModel) {
+ configWrapper.getConfig().setDataObjectModel(dataObjectModel);
+ }
+
+ /**
+ * Add a select command
+ * @param name
+ * @param sql
+ * @return
+ */
+ public Command addSelectCommand(String name, String sql) {
+ return configWrapper.addCommand(name, sql, "select");
+ }
+
+ /**
+ * Add a update command
+ * @param name
+ * @param sql
+ * @return
+ */
+ public Command addUpdateCommand(String name, String sql) {
+ return configWrapper.addCommand(name, sql, "update");
+ }
+
+ /**
+ * Add a insert command
+ * @param name
+ * @param sql
+ * @return
+ */
+ public Command addInsertCommand(String name, String sql) {
+ return configWrapper.addCommand(name, sql, "insert");
+ }
+
+ /**
+ * Add a delete command
+ * @param name
+ * @param sql
+ * @return
+ */
+ public Command addDeleteCommand(String name, String sql) {
+ return configWrapper.addCommand(name, sql, "delete");
+ }
+
+ /**
+ * Get a reference to the config object
+ * @return
+ */
+ public Config getConfig() {
+ return config;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Converter.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Converter.java
new file mode 100644
index 0000000000..24f2e5ee2e
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Converter.java
@@ -0,0 +1,54 @@
+/*
+ * 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;
+
+/**
+ * A lightweight Table-column <--> DataObject-property converter framework. Converters
+ * allow a user to insert a transformation between a column value
+ * and is destination DataObject property value. For example, by default, a VARCHAR
+ * column will be represented as a String in its corresponding
+ * DataObject property. A user could insert a converter that transforms the the VARCHAR
+ * value to an Integer. If this is done then although the column
+ * returns character data, the DataObject property will be an Integer
+ *
+ *
+ */
+public interface Converter {
+
+ /**
+ * Transform the columnData object to a new value and possibly
+ * new type. This should be the invers operation of #getColumnValue
+ *
+ * @param columnData
+ * The column value to transorm
+ * @return Returns the transformed value
+ */
+ Object getPropertyValue(Object columnData);
+
+ /**
+ * Transform the columnData object to a new value and possibly new
+ * type. This should be the invers operation of #getPropertyValue
+ *
+ * @param propertyData
+ * The property value to transform
+ * @return Returns the transformed value
+ */
+ Object getColumnValue(Object propertyData);
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/DAS.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/DAS.java
new file mode 100644
index 0000000000..43f1e30d1a
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/DAS.java
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+import org.apache.tuscany.das.rdb.impl.DASFactoryImpl;
+
+import commonj.sdo.DataObject;
+
+/**
+ * A CommandGroup represents a set of {@link Command} and single {@link ApplyChangesCommand}
+ * that are created from a common config file.
+ *
+ */
+public interface DAS {
+
+ DASFactory FACTORY = new DASFactoryImpl();
+
+ /**
+ * The change history is scanned and modifications to the graph of data objects are flushed to the database.
+ *
+ * @param root
+ * the topmost containing data object
+ */
+ void applyChanges(DataObject root);
+
+ /**
+ * Gets the named command from this factory's inventory
+ *
+ * @param name
+ * The identifying name of the requested command
+ * @return Returns the identified command
+ */
+ Command getCommand(String name);
+
+ /**
+ * If the CommandGroup is managing connections then this method must be called
+ * when the client is done with the instance.
+ *
+ */
+ void releaseResources();
+
+ /**
+ * Creates a Command based on the provided SQL statement
+ *
+ * @param sql
+ * The SQL statement
+ * @return returns a Command instance
+ */
+ Command createCommand(String sql);
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/DASFactory.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/DASFactory.java
new file mode 100644
index 0000000000..313fff225a
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/DASFactory.java
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+import java.io.InputStream;
+import java.sql.Connection;
+
+import org.apache.tuscany.das.rdb.config.Config;
+
+/**
+ * A DASFactory produces {@link DAS} instances.
+ */
+public interface DASFactory {
+
+ /**
+ * Creates a DAS based on the provided config file stream
+ *
+ * @param configStream
+ * A stream over a DAS config file
+ * @return returns a DAS instance
+ */
+ DAS createDAS(InputStream configStream);
+
+ /**
+ * Creates a DAS based on the provide config file stream and connection
+ * @param configStream
+ * @param connection
+ * @return
+ */
+ DAS createDAS(InputStream configStream, Connection connection);
+
+ /**
+ * Creates a DAS based on the provided config
+ *
+ * @param config
+ * A DAS config object
+ * @return returns a DAS instance
+ */
+ DAS createDAS(Config config);
+
+ /**
+ * Creates a DAS based on the provided config and connection
+ * @param config
+ * @param connection
+ * @return
+ */
+ DAS createDAS(Config config, Connection connection);
+
+ /**
+ * Creates a DAS based on the provided connection
+ * @param connection
+ * @return
+ */
+ DAS createDAS(Connection connection);
+
+
+}
+
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Pager.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Pager.java
new file mode 100644
index 0000000000..aa18558fce
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/Pager.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+import commonj.sdo.DataObject;
+
+/**
+ * An iterator-like interface to conveniently move through chunks of data. The
+ * idea is that a Pager works with a read Command. The read command
+ * returns a large amount of data and the client wants to work with chunks
+ * of it at a time. So the Pager is created on the command and each call to
+ * next returns the next chunk of data. This is done completely disconnected.
+ * No cursor is maintained between calls to #next.
+ *
+ * TODO - This is very preliminary. We need to look at this interface
+ * in the context of disonnected scenarios such as a web app. The Pager instance
+ * will probably be saved in session so it must be very light and cannot
+ * reference a connection. Also, we probably need to define a factory or add a
+ * method to set page size.
+ *
+ *
+ */
+public interface Pager {
+
+ /**
+ * Get the next page of data
+ *
+ * @return the next page of data
+ */
+ DataObject next();
+
+ /**
+ * Get the page prior to the last page returned
+ *
+ * @return the previous page
+ */
+ DataObject previous();
+
+ /**
+ * Return a specific identified page.
+ *
+ * @param page
+ * The number of the page to return
+ * @return the indicated page
+ */
+ DataObject getPage(int page);
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java
new file mode 100644
index 0000000000..ec5c6f5deb
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java
@@ -0,0 +1,738 @@
+/*
+ * 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.config.wrapper;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.Column;
+import org.apache.tuscany.das.rdb.config.Command;
+import org.apache.tuscany.das.rdb.config.Config;
+import org.apache.tuscany.das.rdb.config.ConfigFactory;
+import org.apache.tuscany.das.rdb.config.ConnectionInfo;
+import org.apache.tuscany.das.rdb.config.ConnectionProperties;
+import org.apache.tuscany.das.rdb.config.Create;
+import org.apache.tuscany.das.rdb.config.Delete;
+import org.apache.tuscany.das.rdb.config.KeyPair;
+import org.apache.tuscany.das.rdb.config.Parameters;
+import org.apache.tuscany.das.rdb.config.Relationship;
+import org.apache.tuscany.das.rdb.config.Table;
+import org.apache.tuscany.das.rdb.config.Update;
+
+import commonj.sdo.Property;
+
+public class MappingWrapper {
+
+ private static final ConfigFactory FACTORY = ConfigFactory.INSTANCE;
+
+ private final Logger logger = Logger.getLogger(MappingWrapper.class);
+
+ private Config config;
+
+ public MappingWrapper() {
+ config = FACTORY.createConfig();
+ //JIRA-952
+ this.checkSchemaNameSupport();
+ }
+
+ //JIRA-952 - check if there is any entry with no schemaName when support is ON
+ public void checkSchemaNameSupport(){
+ if(config.isDatabaseSchemaNameSupported()){
+ List tableList = config.getTable();
+ for(int i=0; i<tableList.size(); i++){
+ Table t = (Table)tableList.get(i);
+ if(t.getSchemaName() == null || t.getSchemaName().equals("")){
+ throw new RuntimeException("No schemaName provided for tableName "+t.getTableName()+" when schemaNameSupport is ON");
+ }
+
+ if(t.getTypeName()==null){
+ t.setTypeName(t.getSchemaName()+"."+t.getTableName());
+ }
+ }
+ }
+ }
+ public MappingWrapper(Config mapping) {
+ if (mapping == null) {
+ this.config = FACTORY.createConfig();
+ } else {
+ this.config = mapping;
+ }
+ //JIRA-952
+ checkSchemaNameSupport();
+ }
+
+ public Config getConfig() {
+ return this.config;
+ }
+
+ public Table getTable(String tableName) {
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Looking for table " + tableName);
+ }
+
+ Iterator i = config.getTable().iterator();
+ while (i.hasNext()) {
+ Table t = (Table) i.next();
+ //JIRA-952
+ if(this.config.isDatabaseSchemaNameSupported()){
+ if (tableName.equalsIgnoreCase(t.getSchemaName()+"."+t.getTableName())) {
+ return t;
+ }
+ }else{
+ if (tableName.equalsIgnoreCase(t.getTableName())) {
+ return t;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public Table getTableByTypeName(String typeName) {
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Looking for table by property: " + typeName);
+ }
+
+ Iterator i = config.getTable().iterator();
+ while (i.hasNext()) {
+ Table t = (Table) i.next();
+ TableWrapper wrapper = new TableWrapper(t);
+ if (typeName.equals(wrapper.getTypeName())) {
+ return t;
+ }
+ }
+ return null;
+
+ }
+
+ public void addImpliedRelationship(String parentTableName, String childTableName, String fkColumnName) {
+
+ // Don't create a relationship for something like Book.Book_ID
+ if (parentTableName.equalsIgnoreCase(childTableName)) {
+ return;
+ }
+
+ // Don't create a relationship if one already exists in the config
+ Iterator i = config.getRelationship().iterator();
+ while (i.hasNext()) {
+ Relationship r = (Relationship) i.next();
+ if (r.getPrimaryKeyTable().equals(parentTableName) && r.getForeignKeyTable().equals(childTableName)) {
+ return;
+ }
+ }
+
+ Relationship r = FACTORY.createRelationship();
+ r.setName(childTableName);
+ r.setPrimaryKeyTable(parentTableName);
+ r.setForeignKeyTable(childTableName);
+
+ KeyPair pair = FACTORY.createKeyPair();
+ pair.setPrimaryKeyColumn("ID");
+ pair.setForeignKeyColumn(fkColumnName);
+
+ r.getKeyPair().add(pair);
+ r.setMany(true);
+
+ config.getRelationship().add(r);
+ }
+
+ public Relationship addRelationship(String parentName, String childName) {
+
+ //JIRA-952
+ QualifiedColumn parent = null;
+ QualifiedColumn child = null;
+
+ if(this.config.isDatabaseSchemaNameSupported()){
+ parent = new QualifiedColumn(parentName, true);
+ child = new QualifiedColumn(childName, true);
+ }
+ else{
+ parent = new QualifiedColumn(parentName);
+ child = new QualifiedColumn(childName);
+ }
+
+ Relationship r = FACTORY.createRelationship();
+ //JIRA-952
+ if(this.config.isDatabaseSchemaNameSupported()){
+ r.setName(child.getSchemaName()+"."+child.getTableName());
+ r.setPrimaryKeyTable(parent.getSchemaName()+"."+parent.getTableName());
+ r.setForeignKeyTable(child.getSchemaName()+"."+child.getTableName());
+ }
+ else{
+ r.setName(child.getTableName());
+ r.setPrimaryKeyTable(parent.getTableName());
+ r.setForeignKeyTable(child.getTableName());
+ }
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Created relationship from " + r.getPrimaryKeyTable()
+ + " to " + r.getForeignKeyTable() + " named " + r.getName());
+ }
+
+ KeyPair pair = FACTORY.createKeyPair();
+ pair.setPrimaryKeyColumn(parent.getColumnName());
+ pair.setForeignKeyColumn(child.getColumnName());
+
+ r.getKeyPair().add(pair);
+ r.setMany(true);
+
+ config.getRelationship().add(r);
+
+ return r;
+
+ }
+
+ public Relationship addRelationship(Vector parentNames, Vector childNames) {
+ //create vector for each
+ if(parentNames.size() != childNames.size()){
+ throw new RuntimeException("Can not for relationship for multiple keys, different sizes");
+ }
+
+ Vector parentColumns = new Vector();
+ Vector childColumns = new Vector();
+
+ for(int i=0; i<parentNames.size(); i++){
+ QualifiedColumn parent = null;
+ QualifiedColumn child = null;
+
+ if(this.config.isDatabaseSchemaNameSupported()){
+ parent = new QualifiedColumn((String)parentNames.get(i), true);
+ child = new QualifiedColumn((String)childNames.get(i), true);
+ }
+ else{
+ parent = new QualifiedColumn((String)parentNames.get(i));
+ child = new QualifiedColumn((String)childNames.get(i));
+ }
+
+ parentColumns.add(parent);
+ childColumns.add(child);
+ }
+
+ //all parent columns should be from same table and schema
+ //all child columns should be from same table and schema
+ checkTableNames(parentColumns);
+ checkSchemaNames(parentColumns);
+
+ checkTableNames(childColumns);
+ checkSchemaNames(childColumns);
+
+ Relationship r = FACTORY.createRelationship();
+ //JIRA-952
+ if(this.config.isDatabaseSchemaNameSupported()){
+ r.setName(((QualifiedColumn)childColumns.get(0)).getSchemaName()+"."
+ +((QualifiedColumn)childColumns.get(0)).getTableName());
+ r.setPrimaryKeyTable(((QualifiedColumn)parentColumns.get(0)).getSchemaName()+"."
+ +((QualifiedColumn)parentColumns.get(0)).getTableName());
+ r.setForeignKeyTable(((QualifiedColumn)childColumns.get(0)).getSchemaName()+"."
+ +((QualifiedColumn)childColumns.get(0)).getTableName());
+ }
+ else{
+ r.setName(((QualifiedColumn)childColumns.get(0)).getTableName());
+ r.setPrimaryKeyTable(((QualifiedColumn)parentColumns.get(0)).getTableName());
+ r.setForeignKeyTable(((QualifiedColumn)childColumns.get(0)).getTableName());
+ }
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Created relationship from " + r.getPrimaryKeyTable()
+ + " to " + r.getForeignKeyTable() + " named " + r.getName());
+ }
+
+ KeyPair pair = null;
+
+ for(int i=0; i<parentColumns.size(); i++){
+ pair = FACTORY.createKeyPair();
+ pair.setPrimaryKeyColumn(((QualifiedColumn)parentColumns.get(i)).getColumnName());
+ pair.setForeignKeyColumn(((QualifiedColumn)childColumns.get(i)).getColumnName());
+ r.getKeyPair().add(pair);
+ }
+
+ r.setMany(true);
+ config.getRelationship().add(r);
+
+ return r;
+ }
+
+ public void checkTableNames(Vector columns){
+ String expectedTableName = ((QualifiedColumn)columns.get(0)).getTableName();
+
+ for(int i=0; i<columns.size(); i++){
+ QualifiedColumn currColumn = (QualifiedColumn)columns.get(i);
+ String currTableName = currColumn.getTableName();
+
+ if(!currTableName.equals(expectedTableName)){
+ throw new RuntimeException("Columns in one side of relationship can not be from different tables");
+ }
+ }
+ }
+
+ public void checkSchemaNames(Vector columns){
+ if(!this.config.isDatabaseSchemaNameSupported()){
+ return;
+ }
+
+ String expectedSchemaName = ((QualifiedColumn)columns.get(0)).getSchemaName();
+
+ for(int i=0; i<columns.size(); i++){
+ QualifiedColumn currColumns = (QualifiedColumn)columns.get(i);
+ String currSchemaName = currColumns.getSchemaName();
+
+ if(!currSchemaName.equals(expectedSchemaName)){
+ throw new RuntimeException("Columns in one side of relationship can not be from different schema");
+ }
+ }
+ }
+ public void addPrimaryKey(String columnName) {
+ addPrimaryKey(Collections.singletonList(columnName));
+ }
+
+ public void addPrimaryKey(List columnNames) {
+
+ Iterator i = columnNames.iterator();
+ while (i.hasNext()) {
+ String columnName = (String) i.next();
+
+ QualifiedColumn pkColumn = null;
+ pkColumn = new QualifiedColumn(columnName, this.config.isDatabaseSchemaNameSupported());
+ //Table t = findOrCreateTable(pkColumn.getTableName());
+ Table t = findOrCreateTable(pkColumn);
+ Column c = findOrCreateColumn(t, pkColumn.getColumnName());
+ c.setPrimaryKey(true);
+ }
+ }
+
+ public String getTableTypeName(String tableName) {
+ Table t = getTable(tableName);
+ if (t == null) {
+ return tableName;
+ }
+ String propertyName = t.getTypeName();
+
+ if (propertyName == null) {
+ return tableName;
+ }
+
+ return propertyName;
+ }
+
+ public Column getColumn(Table t, String columnName) {
+ if (t == null) {
+ return null;
+ }
+ Iterator i = t.getColumn().iterator();
+ while (i.hasNext()) {
+ Column c = (Column) i.next();
+ if (c.getColumnName().equals(columnName)) {
+ return c;
+ }
+ }
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("WARNING: Could not find column " + columnName + " in table " + t.getTableName());
+ }
+
+ return null;
+ }
+
+ public Column getColumnByPropertyName(Table t, String propertyName) {
+ if (t == null) {
+ return null;
+ }
+
+ Iterator i = t.getColumn().iterator();
+ while (i.hasNext()) {
+ Column c = (Column) i.next();
+
+ if (c.getColumnName().equals(propertyName)) {
+ return c;
+ }
+
+ if (c.getPropertyName() != null && c.getPropertyName().equals(propertyName)) {
+ return c;
+ }
+ }
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("WARNING: Could not find column " + propertyName + " in table " + t.getTableName());
+ }
+
+ return null;
+ }
+
+ public String getColumnPropertyName(String tableName, String columnName) {
+ Table t = getTable(tableName);
+ Column c = getColumn(t, columnName);
+ if (c == null) {
+ return columnName;
+ }
+
+ String propertyName = c.getPropertyName();
+ if (propertyName == null) {
+ return c.getColumnName();
+ }
+
+ return propertyName;
+ }
+
+ public Table addTable(String tableName, String typeName) {
+ Table table = getTable(tableName);
+ if (table != null) {
+ throw new RuntimeException("Table " + tableName + "already exists");
+ }
+
+ table = ConfigFactory.INSTANCE.createTable();
+ table.setTableName(tableName);
+ table.setTypeName(typeName);
+ config.getTable().add(table);
+
+ return table;
+ }
+
+ //JIRA-952
+ public Table addTable(String tableName, String schemaName, String typeName) {
+ Table table = null;
+
+ if(this.config.isDatabaseSchemaNameSupported()){
+ table = getTable(schemaName+"."+tableName);
+ }
+ else{
+ table = getTable(tableName);
+ }
+
+ if (table != null) {
+ if(this.config.isDatabaseSchemaNameSupported()){
+ throw new RuntimeException("Table " + schemaName+"."+tableName + "already exists");
+ }
+ else{
+ throw new RuntimeException("Table " + tableName + "already exists");
+ }
+ }
+
+ table = ConfigFactory.INSTANCE.createTable();
+ table.setTableName(tableName);
+
+ if(this.config.isDatabaseSchemaNameSupported()){
+ table.setSchemaName(schemaName);
+ }
+ else{
+ table.setSchemaName("");
+ }
+
+ table.setTypeName(typeName);
+ config.getTable().add(table);
+
+ return table;
+ }
+ public Column addColumn(Table table, String name, String propertyName) {
+ Column column = ConfigFactory.INSTANCE.createColumn();
+ column.setColumnName(name);
+ column.setPropertyName(propertyName);
+
+ table.getColumn().add(column);
+ return column;
+ }
+
+ //JIRA-952
+ private Table findOrCreateTable(String schemaName, String tableName) {
+ Table table = null;
+
+ if(this.config.isDatabaseSchemaNameSupported()){
+ table = getTable(schemaName+"."+tableName);
+ }
+ else{
+ table = getTable(tableName);
+ }
+ if (table == null) {
+ table = ConfigFactory.INSTANCE.createTable();
+ table.setTableName(tableName);
+ table.setSchemaName(schemaName);
+
+ if(this.config.isDatabaseSchemaNameSupported()){
+ table.setTypeName(schemaName+"."+tableName);
+ }
+ else{
+ table.setTypeName(tableName);
+ }
+ config.getTable().add(table);
+ }
+ return table;
+
+ }
+
+ //JIRA-952
+ private Table findOrCreateTable(QualifiedColumn column) {
+ Table table = null;
+ if(this.config.isDatabaseSchemaNameSupported()){
+ table = getTable(column.getSchemaName()+"."+column.getTableName());
+ }
+ else{
+ table = getTable(column.getTableName());
+ }
+
+ if (table == null) {
+ table = ConfigFactory.INSTANCE.createTable();
+ table.setTableName(column.getTableName());
+ table.setSchemaName(column.getSchemaName());
+ config.getTable().add(table);
+ }
+ return table;
+
+ }
+ private Column findOrCreateColumn(Table t, String name) {
+ Iterator i = t.getColumn().iterator();
+ while (i.hasNext()) {
+ Column c = (Column) i.next();
+ if (name.equals(c.getColumnName())) {
+ return c;
+ }
+ }
+
+ Column c = ConfigFactory.INSTANCE.createColumn();
+ c.setColumnName(name);
+ t.getColumn().add(c);
+ return c;
+ }
+
+ public boolean hasRecursiveRelationships() {
+ if (config != null) {
+ Iterator i = getConfig().getRelationship().iterator();
+ while (i.hasNext()) {
+ Relationship r = (Relationship) i.next();
+ if (r.getPrimaryKeyTable().equals(r.getForeignKeyTable())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public Collection getRelationshipsByChildTable(String name) {
+ List results = new ArrayList();
+ if (config != null) {
+ Iterator i = getConfig().getRelationship().iterator();
+ while (i.hasNext()) {
+ Relationship r = (Relationship) i.next();
+ if (name.equals(r.getForeignKeyTable())) {
+ results.add(r);
+ }
+ }
+ }
+ return results;
+ }
+
+ // TODO optimize
+ public List getInsertOrder() {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Getting insert order");
+ }
+
+ List inserts = new ArrayList();
+ Map parentToChild = new HashMap();
+
+ List parents = new ArrayList();
+ List children = new ArrayList();
+ if (config != null) {
+ Iterator i = getConfig().getRelationship().iterator();
+ while (i.hasNext()) {
+ Relationship r = (Relationship) i.next();
+ parents.add(r.getPrimaryKeyTable());
+ children.add(r.getForeignKeyTable());
+ parentToChild.put(r.getPrimaryKeyTable(), r.getForeignKeyTable());
+ }
+ while (parents.size() > 0) {
+ String parent = (String) parents.get(0);
+ if (!children.contains(parent)) {
+ if (!inserts.contains(parent)) {
+ inserts.add(parent);
+ }
+ String child = (String) parentToChild.get(parent);
+ if (!inserts.contains(child)) {
+ inserts.add(child);
+ }
+ parents.remove(parent);
+ children.remove(child);
+ } else {
+ parents.add(parents.remove(0));
+ }
+ }
+ inserts.addAll(children);
+ }
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug(inserts);
+ }
+
+ return inserts;
+ }
+
+ public List getDeleteOrder() {
+ List deleteOrder = new ArrayList();
+ deleteOrder.addAll(getInsertOrder());
+ Collections.reverse(deleteOrder);
+ return deleteOrder;
+ }
+
+ //JIRA-952
+ public void addConverter(String name, String converter) {
+ QualifiedColumn column = new QualifiedColumn(name, this.config.isDatabaseSchemaNameSupported());
+ Table t = null;
+ t = findOrCreateTable(column);
+ Column c = findOrCreateColumn(t, column.getColumnName());
+ c.setConverterClassName(converter);
+ }
+
+ public String getConverter(String tableName, String columnName) {
+ Table t = getTable(tableName);
+ Column c = getColumn(t, columnName);
+ if (c != null) {
+ return c.getConverterClassName();
+ }
+ return null;
+ }
+
+ public Map getConverters(Table table) {
+ Map converters = new HashMap();
+
+ Iterator columns = table.getColumn().iterator();
+ while (columns.hasNext()) {
+ Column c = (Column) columns.next();
+ if (c.getConverterClassName() != null) {
+ String property = c.getPropertyName();
+ if (property == null) {
+ property = c.getColumnName();
+ }
+ converters.put(property, c.getConverterClassName());
+ }
+ }
+ return converters;
+ }
+
+ public Relationship getRelationshipByReference(Property ref) {
+ Iterator i = config.getRelationship().iterator();
+ while (i.hasNext()) {
+ Relationship r = (Relationship) i.next();
+ if (ref.getName().equals(r.getName()) || ref.getOpposite().getName().equals(r.getName())) {
+ return r;
+ }
+ }
+ throw new RuntimeException("Could not find relationship " + ref.getName() + " in the configuration");
+ }
+
+ public Relationship getRelationshipByName(String name) {
+ Iterator i = config.getRelationship().iterator();
+ while (i.hasNext()) {
+ Relationship r = (Relationship) i.next();
+ if (name.equals(r.getName())) {
+ return r;
+ }
+ }
+ throw new RuntimeException("Could not find relationship " + name + " in the configuration");
+ }
+
+ public void addUpdateStatement(Table table, String statement, Parameters parameters) {
+
+ Update update = ConfigFactory.INSTANCE.createUpdate();
+ update.setSql(statement);
+ update.setParameters(parameters);
+ table.setUpdate(update);
+
+ }
+
+ public void addDeleteStatement(Table table, String statement, Parameters parameters) {
+
+ Delete delete = ConfigFactory.INSTANCE.createDelete();
+ delete.setSql(statement);
+ delete.setParameters(parameters);
+ table.setDelete(delete);
+
+ }
+
+ public void addCreateStatement(Table table, String statement, Parameters parameters) {
+
+ Create create = ConfigFactory.INSTANCE.createCreate();
+ create.setSql(statement);
+ create.setParameters(parameters);
+ table.setCreate(create);
+
+ }
+
+ //JIRA-948 support for driver manager connection
+ public void addConnectionInfo(String dataSourceName, boolean managedtx){
+ ConnectionInfo info = ConfigFactory.INSTANCE.createConnectionInfo();
+ info.setDataSource(dataSourceName);
+ info.setManagedtx(managedtx);
+
+ config.setConnectionInfo(info);
+ }
+
+ public void addConnectionInfo(String driverClass, String connectionURL, String user, String password, int loginTimeout) {
+ ConnectionInfo info = ConfigFactory.INSTANCE.createConnectionInfo();
+
+ ConnectionProperties connectionProperties = ConfigFactory.INSTANCE.createConnectionProperties();
+ connectionProperties.setDriverClass(driverClass);
+ connectionProperties.setDatabaseURL(connectionURL);
+ connectionProperties.setUserName(user);
+ connectionProperties.setPassword(password);
+ connectionProperties.setLoginTimeout(loginTimeout);
+
+ info.setConnectionProperties(connectionProperties);
+ config.setConnectionInfo(info);
+ }
+ //JIRA-948 end
+
+ public Command addCommand(String name, String sql, String kind) {
+ Command cmd = ConfigFactory.INSTANCE.createCommand();
+ cmd.setName(name);
+ cmd.setKind(kind);
+ cmd.setSQL(sql);
+
+ config.getCommand().add(cmd);
+
+ return cmd;
+ }
+
+ //JIRA-952
+ public void addImpliedPrimaryKey(String schemaName, String tableName, String columnName) {
+ Table t = findOrCreateTable(schemaName, tableName);//JIRA-952
+
+ Iterator i = t.getColumn().iterator();
+ boolean hasPK = false;
+ while (i.hasNext()) {
+ Column c = (Column) i.next();
+ if (c.isPrimaryKey()) {
+ hasPK = true;
+ }
+ }
+
+ if (!hasPK) {
+ Column c = findOrCreateColumn(t, columnName);
+ c.setPrimaryKey(true);
+ }
+
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/QualifiedColumn.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/QualifiedColumn.java
new file mode 100644
index 0000000000..95e5e78c54
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/QualifiedColumn.java
@@ -0,0 +1,94 @@
+/*
+ * 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.config.wrapper;
+
+import org.apache.log4j.Logger;
+
+public class QualifiedColumn {
+
+ private final String tableName;
+
+ private final String columnName;
+ private final String schemaName;//JIRA-952
+
+ private final Logger logger = Logger.getLogger(QualifiedColumn.class);
+
+ public QualifiedColumn(String name) {
+ this.schemaName = "";
+ int index = name.indexOf('.');
+ if ( index == -1 ) {
+ throw new RuntimeException("Column " + name + " must be qualified with a table name");
+ }
+ tableName = name.substring(0, index);
+ columnName = name.substring(index + 1);
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Table name: " + tableName);
+ this.logger.debug("Column name: " + columnName);
+ }
+ }
+
+ //JIRA-952
+ public QualifiedColumn(String name, boolean isDatabaseSchemaNameSupported) {
+ int index = name.indexOf('.');
+ if ( index == -1 ) {
+ throw new RuntimeException("Column " + name + " must be qualified with a table name and optional schema name");
+ }
+
+ int lastIndex = name.lastIndexOf('.');
+
+ if(index == lastIndex && isDatabaseSchemaNameSupported){
+ throw new RuntimeException("Column " + name + " must be qualified with a table name and schema name");
+ }
+
+ if(isDatabaseSchemaNameSupported){
+ schemaName = name.substring(0, index);
+ tableName = name.substring(index+1, lastIndex);
+ columnName = name.substring(lastIndex + 1);
+ }
+ else{
+ schemaName = "";
+ tableName = name.substring(0, index);
+ columnName = name.substring(index + 1);
+ }
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Table name: " + tableName);
+ this.logger.debug("Column name: " + columnName);
+ }
+ }
+ public String getTableName() {
+ return this.tableName;
+ }
+
+ //JIRA-952
+ public String getSchemaName() {
+ return this.schemaName;
+ }
+ public String getColumnName() {
+ return this.columnName;
+ }
+ //JIRA-952
+ public String toString(){
+ if(this.schemaName == null || this.schemaName.equals(""))
+ return this.tableName+"."+this.columnName;
+ else
+ return this.schemaName+"."+this.tableName+"."+this.columnName;
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/RelationshipWrapper.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/RelationshipWrapper.java
new file mode 100644
index 0000000000..0e4447bf8b
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/RelationshipWrapper.java
@@ -0,0 +1,47 @@
+/*
+ * 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.config.wrapper;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tuscany.das.rdb.config.KeyPair;
+import org.apache.tuscany.das.rdb.config.Relationship;
+
+public class RelationshipWrapper {
+
+ private Relationship relationship;
+
+ public RelationshipWrapper(Relationship r) {
+ this.relationship = r;
+ }
+
+ public Collection getForeignKeys() {
+ List keys = new ArrayList();
+ Iterator i = this.relationship.getKeyPair().iterator();
+ while (i.hasNext()) {
+ KeyPair pair = (KeyPair) i.next();
+ keys.add(pair.getForeignKeyColumn());
+ }
+ return keys;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/TableWrapper.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/TableWrapper.java
new file mode 100644
index 0000000000..ef420eedf2
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/TableWrapper.java
@@ -0,0 +1,149 @@
+/*
+ * 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.config.wrapper;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tuscany.das.rdb.config.Column;
+import org.apache.tuscany.das.rdb.config.Table;
+
+public class TableWrapper {
+
+ private Table table;
+
+ public TableWrapper(Table table) {
+ this.table = table;
+ }
+
+ public String getTypeName() {
+ return table.getTypeName() == null ? table.getTableName() : table.getTypeName();
+ }
+
+ public String getTableName() {
+ return table.getTableName();
+ }
+
+ public Collection getPrimaryKeyNames() {
+ List pkNames = new ArrayList();
+ Iterator i = table.getColumn().iterator();
+ while (i.hasNext()) {
+ Column c = (Column) i.next();
+ if (c.isPrimaryKey()) {
+ pkNames.add(c.getColumnName());
+ }
+ }
+ return pkNames;
+ }
+
+ public Collection getPrimaryKeyProperties() {
+
+ List keyProperties = new ArrayList();
+ Iterator columns = table.getColumn().iterator();
+ while (columns.hasNext()) {
+ Column c = (Column) columns.next();
+ if (c.isPrimaryKey()) {
+ keyProperties.add(getColumnPropertyName(c));
+ }
+ }
+
+ return keyProperties;
+ }
+
+ private String getColumnPropertyName(Column c) {
+ if (c.getPropertyName() != null) {
+ return c.getPropertyName();
+ }
+
+ return c.getColumnName();
+ }
+
+ public boolean isGeneratedColumnProperty(String name) {
+ Column c = getColumnByPropertyName(name);
+ return c == null ? false : c.isGenerated();
+ }
+
+ public String getConverter(String propertyName) {
+ Column c = getColumnByPropertyName(propertyName);
+ return (c == null) ? null : c.getConverterClassName();
+ }
+
+ public Column getColumnByPropertyName(String propertyName) {
+ Iterator columns = table.getColumn().iterator();
+ while (columns.hasNext()) {
+ Column c = (Column) columns.next();
+ String property = c.getPropertyName();
+ if (property == null) {
+ property = c.getColumnName();
+ }
+ if (propertyName.equals(property)) {
+ return c;
+ }
+ }
+
+ return null;
+ }
+
+ public Column getCollisionColumn() {
+ Iterator columns = table.getColumn().iterator();
+ while (columns.hasNext()) {
+ Column c = (Column) columns.next();
+ if (c.isCollision()) {
+ return c;
+ }
+ }
+
+ return null;
+
+ }
+
+ public String getCollisionColumnPropertyName() {
+ Column c = getCollisionColumn();
+ if (c.getPropertyName() != null) {
+ return c.getPropertyName();
+ }
+ return c.getColumnName();
+
+ }
+
+ public String getManagedColumnPropertyName() {
+ Iterator i = table.getColumn().iterator();
+ while (i.hasNext()) {
+ Column c = (Column) i.next();
+ if (c.isCollision() && c.isManaged()) {
+ return c.getPropertyName() == null ? c.getColumnName() : c.getPropertyName();
+ }
+ }
+ return null;
+
+ }
+
+ public Column getManagedColumn() {
+ Iterator i = table.getColumn().iterator();
+ while (i.hasNext()) {
+ Column c = (Column) i.next();
+ if (c.isCollision() && c.isManaged()) {
+ return c;
+ }
+ }
+ return null;
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/exception/DataSourceInitializationException.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/exception/DataSourceInitializationException.java
new file mode 100644
index 0000000000..6a644b7ed9
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/exception/DataSourceInitializationException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.exception;
+
+public class DataSourceInitializationException extends RuntimeException {
+
+ private static final long serialVersionUID = 302160989411041041L;
+
+ public DataSourceInitializationException(String string) {
+ super(string);
+ }
+
+ public DataSourceInitializationException(Throwable e){
+ super(e);
+ }
+
+ public DataSourceInitializationException(String string, Throwable e) {
+ super(string, e);
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/exception/OptimisticConcurrencyException.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/exception/OptimisticConcurrencyException.java
new file mode 100644
index 0000000000..dc64d7dc94
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/exception/OptimisticConcurrencyException.java
@@ -0,0 +1,31 @@
+/*
+ * 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.exception;
+
+
+public class OptimisticConcurrencyException extends RuntimeException {
+
+ private static final long serialVersionUID = -8430445422807942933L;
+
+ public OptimisticConcurrencyException(String string) {
+ super(string);
+ }
+
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/BaseGenerator.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/BaseGenerator.java
new file mode 100644
index 0000000000..05d97723a7
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/BaseGenerator.java
@@ -0,0 +1,36 @@
+/*
+ * 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.generator.impl;
+
+import org.apache.tuscany.das.rdb.Converter;
+
+public class BaseGenerator {
+
+ protected Converter getConverter(String converter) {
+ if (converter != null) {
+ try {
+ return (Converter) Thread.currentThread().getContextClassLoader().loadClass(converter).newInstance();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/DeleteGenerator.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/DeleteGenerator.java
new file mode 100644
index 0000000000..ad2a90c841
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/DeleteGenerator.java
@@ -0,0 +1,91 @@
+/*
+ * 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.generator.impl;
+
+import java.util.Iterator;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.Table;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper;
+import org.apache.tuscany.das.rdb.impl.DeleteCommandImpl;
+import org.apache.tuscany.das.rdb.impl.ParameterExtendedImpl;
+import org.apache.tuscany.das.rdb.impl.SDODataTypeHelper;
+import org.apache.tuscany.das.rdb.impl.SDODataTypes;
+
+public final class DeleteGenerator extends BaseGenerator {
+
+ public static final DeleteGenerator INSTANCE = new DeleteGenerator();
+
+ private final Logger logger = Logger.getLogger(DeleteGenerator.class);
+
+ private DeleteGenerator() {
+ super();
+ }
+
+ //JIRA-952
+ private String getDeleteStatement(MappingWrapper mapping, Table t) {
+ TableWrapper table = new TableWrapper(t);
+
+ StringBuffer statement = new StringBuffer();
+ statement.append("delete from ");
+ if(mapping.getConfig().isDatabaseSchemaNameSupported()){
+ statement.append(t.getSchemaName()+"."+t.getTableName());
+ }
+ else{
+ statement.append(t.getTableName());
+ }
+ statement.append(" where ");
+
+ Iterator names = table.getPrimaryKeyNames().iterator();
+ Iterator properties = table.getPrimaryKeyProperties().iterator();
+ while (names.hasNext() && properties.hasNext()) {
+ String name = (String) names.next();
+ statement.append(name);
+ statement.append(" = ?");
+ if (names.hasNext() && properties.hasNext()) {
+ statement.append(" and ");
+ }
+ }
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug(statement.toString());
+ }
+
+ return statement.toString();
+ }
+
+ public DeleteCommandImpl getDeleteCommand(MappingWrapper mapping, Table t) {
+ TableWrapper tw = new TableWrapper(t);
+ DeleteCommandImpl deleteCommand = new DeleteCommandImpl(getDeleteStatement(mapping, t));
+
+ Iterator i = tw.getPrimaryKeyProperties().iterator();
+ for (int idx = 1; i.hasNext(); idx++) {
+ String property = (String) i.next();
+ ParameterExtendedImpl p = new ParameterExtendedImpl();
+ p.setName(property);
+ p.setColumnType(SDODataTypeHelper.columnTypeForSDOType(SDODataTypes.OBJECT));
+ p.setConverter(getConverter(tw.getConverter(property)));
+ p.setIndex(idx);
+ deleteCommand.addParameter(p);
+ }
+ return deleteCommand;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/InsertGenerator.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/InsertGenerator.java
new file mode 100644
index 0000000000..d174629ad9
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/InsertGenerator.java
@@ -0,0 +1,182 @@
+/*
+ * 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.generator.impl;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.Column;
+import org.apache.tuscany.das.rdb.config.Relationship;
+import org.apache.tuscany.das.rdb.config.Table;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+import org.apache.tuscany.das.rdb.config.wrapper.RelationshipWrapper;
+import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper;
+import org.apache.tuscany.das.rdb.impl.InsertCommandImpl;
+import org.apache.tuscany.das.rdb.impl.ParameterExtendedImpl;
+import org.apache.tuscany.das.rdb.impl.SDODataTypeHelper;
+import org.apache.tuscany.das.rdb.util.CollectionsUtil;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+
+public final class InsertGenerator extends BaseGenerator {
+
+ public static final InsertGenerator INSTANCE = new InsertGenerator();
+
+ private final Logger logger = Logger.getLogger(InsertGenerator.class);
+
+ private InsertGenerator() {
+ super();
+ }
+
+ public InsertCommandImpl getInsertCommand(MappingWrapper config, DataObject changedObject, Table t) {
+ List parameters = new ArrayList();
+ TableWrapper table = new TableWrapper(t);
+ StringBuffer statement = new StringBuffer("insert into ");
+ //JIRA-952
+ if(config.getConfig().isDatabaseSchemaNameSupported()){
+ statement.append(t.getSchemaName()+"."+t.getTableName());
+ }
+ else{
+ statement.append(t.getTableName());
+ }
+ HashSet changedProperties = getAttributeProperties(changedObject, config, table);
+ Iterator i;
+ if ( changedProperties.isEmpty() ) {
+ i = changedObject.getType().getProperties().iterator();
+ } else {
+ i = changedProperties.iterator();
+ }
+
+ List attributes = new ArrayList();
+ List generatedKeys = new ArrayList();
+ while (i.hasNext()) {
+ Property attr = (Property) i.next();
+ if ( attr.getType().isDataType()) {
+ if (table.isGeneratedColumnProperty(attr.getName())) {
+ generatedKeys.add(attr.getName());
+ } else {
+ attributes.add(attr.getName());
+ parameters.add(changedObject.getType().getProperty(attr.getName()));
+ }
+ }
+ }
+
+ statement.append("(");
+ Iterator attrs = attributes.iterator();
+ while (attrs.hasNext()) {
+ String name = (String) attrs.next();
+ statement.append("");
+ Column c = config.getColumnByPropertyName(t, name);
+ statement.append(c == null ? name : c.getColumnName());
+ if (attrs.hasNext()) {
+ statement.append(", ");
+ } else {
+ statement.append(")");
+ }
+ }
+
+ statement.append(" values (");
+ for (int idx = 1; idx <= attributes.size(); idx++) {
+ statement.append('?');
+ if (idx < attributes.size()) {
+ statement.append(", ");
+ } else {
+ statement.append(")");
+ }
+ }
+
+ InsertCommandImpl cmd = new InsertCommandImpl(statement.toString(),
+ (String[]) generatedKeys.toArray(new String[0]));
+ Iterator params = parameters.iterator();
+ for (int idx = 1; params.hasNext(); idx++) {
+ Property property = (Property) params.next();
+ ParameterExtendedImpl p = new ParameterExtendedImpl();
+ p.setName(property.getName());
+ p.setType(property.getType());
+ p.setColumnType(SDODataTypeHelper.columnTypeForSDOType(property.getType()));
+ p.setConverter(getConverter(table.getConverter(property.getName())));
+ p.setIndex(idx);
+ cmd.addParameter(p);
+
+ }
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug(statement.toString());
+ }
+
+ return cmd;
+
+ }
+
+ private HashSet getAttributeProperties(DataObject obj, MappingWrapper config, TableWrapper tw) {
+ HashSet fields = new HashSet();
+ Iterator i = obj.getType().getProperties().iterator();
+ while (i.hasNext()) {
+ Property p = (Property) i.next();
+ if (p.getType().isDataType()) {
+ if (obj.isSet(p)) {
+ if (fields.add(p) == false) {
+ throw new RuntimeException("Foreign key properties should not be set when the corrsponding relationship has changed");
+ }
+ }
+ } else {
+ if (obj.isSet(p)) {
+ Relationship relationship = config.getRelationshipByReference(p);
+ if ((p.getOpposite() != null && p.getOpposite().isMany())
+ || (hasState(tw, relationship, obj))) {
+ RelationshipWrapper r = new RelationshipWrapper(relationship);
+ Iterator keys = r.getForeignKeys().iterator();
+ while (keys.hasNext()) {
+ String key = (String) keys.next();
+ String keyProperty = config.getColumnPropertyName(tw.getTableName(), key);
+ Property keyProp = obj.getType().getProperty(keyProperty);
+ if ( keyProp == null )
+ throw new RuntimeException("Invalid foreign key column: " + key);
+ if (fields.add(keyProp) == false) {
+ throw new RuntimeException("Foreign key properties should not be set when the corresponding relationship has changed");
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ return fields;
+
+ }
+
+ private boolean hasState(TableWrapper tw, Relationship rel, DataObject changedObject) {
+
+ if (!rel.isMany()) {
+
+ RelationshipWrapper rw = new RelationshipWrapper(rel);
+ if ((rel.getForeignKeyTable().equals(tw.getTableName()))
+ && (CollectionsUtil.disjoint(tw.getPrimaryKeyProperties(), rw.getForeignKeys()))) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/UpdateGenerator.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/UpdateGenerator.java
new file mode 100644
index 0000000000..9d2a405dc6
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/UpdateGenerator.java
@@ -0,0 +1,228 @@
+/*
+ * 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.generator.impl;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.Column;
+import org.apache.tuscany.das.rdb.config.Table;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+import org.apache.tuscany.das.rdb.config.wrapper.RelationshipWrapper;
+import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper;
+import org.apache.tuscany.das.rdb.impl.CollisionParameter;
+import org.apache.tuscany.das.rdb.impl.ManagedParameterImpl;
+import org.apache.tuscany.das.rdb.impl.OptimisticWriteCommandImpl;
+import org.apache.tuscany.das.rdb.impl.ParameterExtendedImpl;
+import org.apache.tuscany.das.rdb.impl.SDODataTypeHelper;
+import org.apache.tuscany.das.rdb.impl.UpdateCommandImpl;
+
+import commonj.sdo.ChangeSummary;
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.ChangeSummary.Setting;
+
+public final class UpdateGenerator extends BaseGenerator {
+
+ public static final UpdateGenerator INSTANCE = new UpdateGenerator();
+
+ private final Logger logger = Logger.getLogger(UpdateGenerator.class);
+
+ private UpdateGenerator() {
+ super();
+ }
+
+ public UpdateCommandImpl getUpdateCommand(MappingWrapper mapping, DataObject changedObject, Table table) {
+ List parameters = new ArrayList();
+ Type type = changedObject.getType();
+ TableWrapper tableWrapper = new TableWrapper(table);
+ StringBuffer statement = new StringBuffer("update ");
+ if(mapping.getConfig().isDatabaseSchemaNameSupported()){
+ statement.append(table.getSchemaName()+"."+table.getTableName());
+ }
+ else{
+ statement.append(table.getTableName());
+ }
+ statement.append(" set ");
+
+ ChangeSummary summary = changedObject.getDataGraph().getChangeSummary();
+ HashSet changedFields = getChangedFields(mapping, summary, changedObject, tableWrapper);
+ Iterator i = changedFields.iterator();
+
+ int idx = 1;
+ while (i.hasNext()) {
+ Property property = (Property) i.next();
+ Column c = tableWrapper.getColumnByPropertyName(property.getName());
+
+ if ((c == null) || !c.isCollision() || !c.isPrimaryKey()) {
+ String columnName = c == null ? property.getName() : c.getColumnName();
+ appendFieldSet(statement, idx > 1, columnName);
+ parameters.add(createParameter(tableWrapper, property, idx++));
+ }
+ }
+
+ Column c = tableWrapper.getManagedColumn();
+ if (c != null) {
+ appendFieldSet(statement, idx > 1, c.getColumnName());
+ String propertyName = c.getPropertyName() == null ? c.getColumnName() : c.getPropertyName();
+ parameters.add(createManagedParameter(tableWrapper,
+ changedObject.getInstanceProperty(propertyName), idx++));
+ }
+
+ statement.append(" where ");
+
+ Iterator pkColumnNames = tableWrapper.getPrimaryKeyNames().iterator();
+ Iterator pkPropertyNames = tableWrapper.getPrimaryKeyProperties().iterator();
+ while (pkColumnNames.hasNext() && pkPropertyNames.hasNext()) {
+ String columnName = (String) pkColumnNames.next();
+ String propertyName = (String) pkPropertyNames.next();
+ statement.append(columnName);
+ statement.append(" = ?");
+ if (pkColumnNames.hasNext() && pkPropertyNames.hasNext()) {
+ statement.append(" and ");
+ }
+ parameters.add(createParameter(tableWrapper, type.getProperty(propertyName), idx++));
+ }
+
+ if (tableWrapper.getCollisionColumn() == null) {
+ Iterator iter = changedFields.iterator();
+ while (iter.hasNext()) {
+ statement.append(" and ");
+ Property changedProperty = (Property) iter.next();
+ Column column = tableWrapper.getColumnByPropertyName(changedProperty.getName());
+ statement.append(column == null ? changedProperty.getName() : column.getColumnName());
+
+ Object value;
+ Setting setting = summary.getOldValue(changedObject, changedProperty);
+ // Setting is null if this is a relationship change
+ if (setting == null) {
+ value = changedObject.get(changedProperty);
+ } else {
+ value = setting.getValue();
+ }
+
+ if (value == null) {
+ statement.append(" is null");
+ } else {
+ ParameterExtendedImpl param = createCollisionParameter(tableWrapper, changedProperty, idx++);
+ statement.append(" = ?");
+ param.setValue(value);
+ parameters.add(param);
+ }
+
+
+ }
+
+ } else {
+ statement.append(" and ");
+ statement.append(tableWrapper.getCollisionColumn().getColumnName());
+ statement.append(" = ?");
+ parameters.add(createParameter(tableWrapper,
+ type.getProperty(tableWrapper.getCollisionColumnPropertyName()), idx++));
+ }
+
+ UpdateCommandImpl updateCommand = new OptimisticWriteCommandImpl(statement.toString());
+
+ Iterator params = parameters.iterator();
+ while (params.hasNext()) {
+ updateCommand.addParameter((ParameterExtendedImpl) params.next());
+ }
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug(statement.toString());
+ }
+
+ return updateCommand;
+ }
+
+
+
+ private void appendFieldSet(StringBuffer statement, boolean appendComma, String columnName) {
+ if (appendComma) {
+ statement.append(", ");
+ }
+ statement.append(columnName);
+ statement.append(" = ?");
+ }
+
+
+
+ private HashSet getChangedFields(MappingWrapper config, ChangeSummary summary, DataObject obj, TableWrapper tw) {
+ HashSet changes = new HashSet();
+
+ Iterator i = summary.getOldValues(obj).iterator();
+ while (i.hasNext()) {
+ ChangeSummary.Setting setting = (ChangeSummary.Setting) i.next();
+
+ if (setting.getProperty().getType().isDataType()) {
+ if ( changes.add(setting.getProperty()) == false ) {
+ throw new RuntimeException("Foreign key properties should not be set when the corresponding relationship has changed");
+ }
+ } else {
+ Property ref = setting.getProperty();
+ if (!ref.isMany()) {
+ RelationshipWrapper r = new RelationshipWrapper(config.getRelationshipByReference(ref));
+
+ Iterator keys = r.getForeignKeys().iterator();
+ while (keys.hasNext()) {
+ String key = (String) keys.next();
+ String keyProperty = config.getColumnPropertyName(tw.getTableName(), key);
+ Property keyProp = obj.getType().getProperty(keyProperty);
+ if ( keyProp == null )
+ throw new RuntimeException("Invalid foreign key column: " + key);
+ if (changes.add(keyProp) == false) {
+ throw new RuntimeException("Foreign key properties should not be set when the corresponding relationship has changed");
+ }
+ }
+ }
+
+ }
+ }
+ return changes;
+ }
+
+ private ParameterExtendedImpl fillExtendedParameter(ParameterExtendedImpl param, TableWrapper table, Property property, int idx) {
+ param.setName(property.getName());
+ param.setType(property.getType());
+ param.setConverter(getConverter(table.getConverter(property.getName())));
+ if (idx != -1) {
+ param.setIndex(idx);
+ }
+ param.setColumnType(SDODataTypeHelper.columnTypeForSDOType(property.getType()));
+ return param;
+ }
+ private ParameterExtendedImpl createCollisionParameter(TableWrapper tableWrapper, Property property, int i) {
+ ParameterExtendedImpl param = new CollisionParameter();
+ return fillExtendedParameter(param, tableWrapper, property, i);
+ }
+
+ private ParameterExtendedImpl createManagedParameter(TableWrapper table, Property property, int idx) {
+ ParameterExtendedImpl param = new ManagedParameterImpl();
+ return fillExtendedParameter(param, table, property, idx);
+ }
+
+ private ParameterExtendedImpl createParameter(TableWrapper table, Property property, int idx) {
+ ParameterExtendedImpl param = new ParameterExtendedImpl();
+ return fillExtendedParameter(param, table, property, idx);
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DataObjectMaker.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DataObjectMaker.java
new file mode 100644
index 0000000000..58e1fd3ff0
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DataObjectMaker.java
@@ -0,0 +1,120 @@
+/*
+ * 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.graphbuilder.impl;
+
+import java.util.Iterator;
+
+import org.apache.log4j.Logger;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
+
+public class DataObjectMaker {
+
+ private final DataObject rootObject;
+
+ private final Logger logger = Logger.getLogger(DataObjectMaker.class);
+
+ public DataObjectMaker(DataObject root) {
+ this.rootObject = root;
+ }
+
+ /**
+ * @param tableData
+ * @return
+ */
+ public DataObject createAndAddDataObject(TableData tableData, ResultMetadata resultMetadata) {
+ // Get a Type from the package and create a standalone DataObject
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Looking for Type for " + tableData.getTableName());
+ }
+
+ Type tableClass = findTableTypeByPropertyName(tableData.getTableName());
+
+ if (tableClass == null) {
+ throw new RuntimeException("An SDO Type with name " + tableData.getTableName() + " was not found");
+ }
+
+ DataObject obj = DataFactory.INSTANCE.create(tableClass);
+
+ // Now, check to see if the root data object has a containment reference
+ // to this EClass. If so, add it to the graph. If not, it will be taken
+ // care
+ // of when we process relationships
+
+ Iterator i = this.rootObject.getType().getProperties().iterator();
+ while (i.hasNext()) {
+ Property p = (Property) i.next();
+
+ if (p.isContainment() && p.getType().equals(tableClass)) {
+ if (p.isMany()) {
+ rootObject.getList(p).add(obj);
+ } else {
+ this.rootObject.set(p, obj);
+ }
+ }
+
+ }
+
+ Iterator columnNames = resultMetadata.getPropertyNames(tableData.getTableName()).iterator();
+ while (columnNames.hasNext()) {
+ String propertyName = (String) columnNames.next();
+
+ Property p = findProperty(obj.getType(), propertyName);
+ if (p == null) {
+ throw new RuntimeException("Type " + obj.getType().getName()
+ + " does not contain a property named " + propertyName);
+ }
+
+ Object value = tableData.getColumnData(propertyName);
+
+ obj.set(p, value);
+ }
+
+ return obj;
+ }
+
+ // temporary, ignoring case
+ private Property findProperty(Type type, String columnName) {
+ Iterator properties = type.getProperties().iterator();
+ while (properties.hasNext()) {
+ Property p = (Property) properties.next();
+ if (columnName.equalsIgnoreCase(p.getName())) {
+ return p;
+ }
+ }
+ return null;
+ }
+
+ private Type findTableTypeByPropertyName(String tableName) {
+ Iterator i = rootObject.getType().getProperties().iterator();
+ while (i.hasNext()) {
+ Property p = (Property) i.next();
+ if (tableName.equals(p.getType().getName())) {
+ return p.getType();
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DefaultConverter.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DefaultConverter.java
new file mode 100644
index 0000000000..a08f184b9a
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DefaultConverter.java
@@ -0,0 +1,84 @@
+/*
+ * 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.graphbuilder.impl;
+
+import java.sql.Blob;
+import java.sql.SQLException;
+
+import org.apache.tuscany.das.rdb.Converter;
+
+public class DefaultConverter implements Converter {
+
+ public DefaultConverter() {
+ super();
+ }
+
+ public Object getColumnValue(Object data) {
+ return data;
+ }
+
+ public Object getPropertyValue(Object data) {
+ // if (type.isInstance(data))
+ // return data;
+ //
+ // if ( data == null )
+ // return null;
+ //
+ // String name = type.getInstanceClass().getName();
+ // if (name == "java.lang.Byte" || name == "byte") {
+ // return new Byte(data.toString());
+ // }
+ //
+ // else if (name == "java.lang.Double" || name == "double") {
+ // return new Double(data.toString());
+ // }
+ //
+ // else if (name == "java.lang.Float" || name == "float") {
+ // return new Float(data.toString());
+ // }
+ //
+ // else if (name == "java.lang.Integer" || name == "int") {
+ // return new Integer(data.toString());
+ // }
+ //
+ // else if (name == "java.lang.Long" || name == "long") {
+ // return new Long(data.toString());
+ // }
+ //
+ // else if (name == "java.lang.Short" || name == "short") {
+ // return new Short(data.toString());
+ // }
+ //
+ // else if (name == "java.lang.String") {
+ // return String.valueOf(data.toString());
+ // }
+
+ if (data instanceof Blob) {
+ Blob b = (Blob) data;
+ try {
+ return b.getBytes(1, (int) b.length());
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ return data;
+
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/GraphBuilderMetadata.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/GraphBuilderMetadata.java
new file mode 100644
index 0000000000..8559b63b78
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/GraphBuilderMetadata.java
@@ -0,0 +1,279 @@
+/*
+ * 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.graphbuilder.impl;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.Config;
+import org.apache.tuscany.das.rdb.config.Relationship;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+import org.apache.tuscany.das.rdb.impl.ResultSetShape;
+import org.apache.tuscany.sdo.api.SDOUtil;
+
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.helper.HelperContext;
+import commonj.sdo.impl.HelperProvider;
+
+/**
+ */
+public class GraphBuilderMetadata {
+
+ private final Logger logger = Logger.getLogger(GraphBuilderMetadata.class);
+
+ private MappingWrapper configWrapper;
+
+ private final Collection resultSets = new ArrayList();
+
+ private String typeURI;
+
+ private Type rootType;
+
+ private HelperContext defaultHelperContext = HelperProvider.getDefaultContext();
+ private HelperContext helperContext = HelperProvider.getInstance().getDefaultContext();
+
+
+ public GraphBuilderMetadata(Collection results, Config model, ResultSetShape shape) throws SQLException {
+ this.configWrapper = new MappingWrapper(model);
+ if (model != null) {
+ this.typeURI = model.getDataObjectModel();
+ }
+
+ Iterator i = results.iterator();
+ while (i.hasNext()) {
+ ResultSet rs = (ResultSet) i.next();
+ ResultMetadata resultMetadata = new ResultMetadata(rs, configWrapper, shape);
+ resultSets.add(resultMetadata);
+ }
+
+ }
+
+ /**
+ * Returns the collection of ResultMetadata objects
+ */
+ public Collection getResultMetadata() {
+ return this.resultSets;
+ }
+
+ /**
+ * Returns the set of defined relationships
+ */
+
+ public Collection getRelationships() {
+ return configWrapper.getConfig().getRelationship();
+ }
+
+ /**
+ * Returns the root Type
+ */
+ public Type getRootType() {
+ if (this.rootType == null) {
+ if (this.typeURI == null) {
+ createDynamicTypes();
+ } else {
+ createDynamicRoot();
+ }
+ }
+
+ return this.rootType;
+ }
+
+ public MappingWrapper getConfigWrapper() {
+ return this.configWrapper;
+ }
+
+ /**
+ * Creates a set of SDO Types based on the query results and supplied config information
+ */
+
+ private void createDynamicTypes() {
+
+ Type root = SDOUtil.createType(helperContext, getDefaultURI(), "DataGraphRoot", false);
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("GBMD.createDynamicTypes():created Type for "+getDefaultURI());
+ }
+
+ Iterator iter = getResultMetadata().iterator();
+ while (iter.hasNext()) {
+
+ ResultMetadata resultMetadata = (ResultMetadata) iter.next();
+
+ // Create a Type for each Table represented in the ResultSet
+ Iterator names = resultMetadata.getAllTablePropertyNames().iterator();
+ while (names.hasNext()) {
+ String tableName = (String) names.next();
+ if (root.getProperty(tableName) == null) {
+ Type tableType = SDOUtil.createType(helperContext, getDefaultURI(), tableName, false);
+ Property property = SDOUtil.createProperty(root, tableName, tableType);
+ SDOUtil.setMany(property, true);
+ SDOUtil.setContainment(property, true);
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("GBMD.createDynamicTypes():CREATING NEW TABLE TYPE & PROPERTY :"+tableName);
+ }
+ }
+ }
+
+ // TODO tablePropertyMap is temporary until Tuscany-203 is fixed
+ Map tablePropertyMap = new HashMap();
+
+ for (int i = 1; i <= resultMetadata.getResultSetSize(); i++) {
+
+ Property ref = root.getProperty(resultMetadata.getTablePropertyName(i));
+
+ if (ref == null) {
+ throw new RuntimeException("Could not find table " + resultMetadata.getTablePropertyName(i)
+ + " in the SDO model");
+ }
+
+ // TODO Temporary code to check to see if a property has already been added.
+ // Replace when Tuscany-203 is fixed
+ List addedProperties = (List) tablePropertyMap.get(ref.getName());
+ if (addedProperties == null) {
+ addedProperties = new ArrayList();
+ tablePropertyMap.put(ref.getName(), addedProperties);
+ }
+
+
+
+ String columnName = resultMetadata.getColumnPropertyName(i);
+
+ // TODO temporary check until Tuscany-203 is fixed
+ if (!addedProperties.contains(columnName)) {
+ addedProperties.add(columnName);
+ Type atype = resultMetadata.getDataType(i);
+
+ SDOUtil.createProperty(ref.getType(), columnName, atype);
+
+ }
+
+ }
+ }
+
+ MappingWrapper wrapper = getConfigWrapper();
+ Iterator i = getRelationships().iterator();
+ while (i.hasNext()) {
+ Relationship r = (Relationship) i.next();
+
+ String parentName = wrapper.getTableTypeName(r.getPrimaryKeyTable());
+ String childName = wrapper.getTableTypeName(r.getForeignKeyTable());
+
+ if (parentName == null) {
+ throw new RuntimeException("The parent table (" + r.getPrimaryKeyTable()
+ + ") in relationship " + r.getName()
+ + " was not found in the mapping information.");
+ } else if (childName == null) {
+ throw new RuntimeException("The child table (" + r.getForeignKeyTable()
+ + ") in relationship " + r.getName()
+ + " was not found in the mapping information.");
+ }
+
+ Property parentProperty = root.getProperty(parentName);
+ Property childProperty = root.getProperty(childName);
+
+ if (parentProperty == null) {
+ throw new RuntimeException("The parent table (" + parentName + ") in relationship "
+ + r.getName() + " was not found.");
+ } else if (childProperty == null) {
+ throw new RuntimeException("The child table (" + childName + ") in relationship "
+ + r.getName() + " was not found.");
+ }
+
+ Type parent = parentProperty.getType();
+ Type child = childProperty.getType();
+
+ Property parentProp = SDOUtil.createProperty(parent, r.getName(), child);
+ Property childProp = SDOUtil.createProperty(child, r.getName() + "_opposite", parent);
+ SDOUtil.setOpposite(parentProp, childProp);
+ SDOUtil.setOpposite(childProp, parentProp);
+ SDOUtil.setMany(parentProp, r.isMany());
+ }
+
+ this.rootType = root;
+ }
+
+ private String getDefaultURI() {
+ return "http:///org.apache.tuscany.das.rdb/das";
+ }
+
+ /**
+ * Create a dynamic root Type to act as a container Type for a set of generated Types
+ *
+ */
+ private void createDynamicRoot() {
+ Type root = SDOUtil.createType(helperContext, getDefaultURI() + "/DataGraphRoot", "DataGraphRoot", false);
+
+ List types = getDefinedTypes();
+
+ if (types == null) {
+ throw new RuntimeException("SDO Types have not been registered for URI " + typeURI);
+ }
+
+ Iterator i = types.iterator();
+ while (i.hasNext()) {
+ Type type = (Type) i.next();
+ Property property = SDOUtil.createProperty(root, type.getName(), type);
+ SDOUtil.setContainment(property, true);
+ SDOUtil.setMany(property, true);
+ }
+ this.rootType = root;
+ }
+
+ public List getDefinedTypes() {
+ List types = null;
+ List defaultTypes = null;
+ if (this.typeURI == null) {
+ types = SDOUtil.getTypes(helperContext, getDefaultURI());
+ defaultTypes = SDOUtil.getTypes(defaultHelperContext, getDefaultURI());
+ if(defaultTypes != null){
+ if(types == null) {
+ types = defaultTypes;
+ }
+ else {
+ types.addAll(defaultTypes);
+ }
+ }
+ return types;
+ }
+
+ types = SDOUtil.getTypes(helperContext, typeURI);
+ defaultTypes = SDOUtil.getTypes(defaultHelperContext, typeURI);
+ if(defaultTypes != null){
+ if(types == null) {
+ types = defaultTypes;
+ }
+ else {
+ types.addAll(defaultTypes);
+ }
+ }
+
+ if(rootType != null)
+ types.add(rootType);
+ return types;
+
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java
new file mode 100644
index 0000000000..7a96d7f66a
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java
@@ -0,0 +1,104 @@
+/*
+ * 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.graphbuilder.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import commonj.sdo.DataObject;
+
+/**
+ *
+ * Used to store and look up table objects based on primary key This could be a lot more
+ * efficient if we could use LinkedHashMap from JDK 1.4
+ */
+public class MultiTableRegistry implements TableRegistry {
+ private final Logger logger = Logger.getLogger(MultiTableRegistry.class);
+
+ private Map tableNameMap;
+
+ private Map tableValueMap;
+
+ public MultiTableRegistry() {
+ tableNameMap = new HashMap();
+ tableValueMap = new HashMap();
+ }
+
+ /**
+ * Get the table with the specified name and primary key
+ *
+ * @param tableName
+ * @param primaryKey
+ * @return EDataObject
+ */
+ public DataObject get(String tableName, List primaryKey) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Looking for table " + tableName + " with PK " + primaryKey);
+ this.logger.debug("\tReturning " + getPkMap(tableName).get(primaryKey));
+ }
+ return (DataObject) getPkMap(tableName).get(primaryKey);
+ }
+
+ /**
+ * Add the table with the specified name and primary key
+ *
+ * @param tableName
+ * @param primaryKey
+ * @param value
+ */
+ public void put(String tableName, List primaryKey, DataObject value) {
+ if (getPkMap(tableName).put(primaryKey, value) == null) {
+ getCreateValueList(tableName).add(value);
+ }
+ }
+
+ /**
+ * Get the HashMap that contains the primary key to table object mappings.
+ *
+ * @param tableName
+ * @return HashMap
+ */
+ private Map getPkMap(String tableName) {
+ Map pkMap = (HashMap) tableNameMap.get(tableName);
+ if (pkMap == null) {
+ pkMap = new HashMap();
+ tableNameMap.put(tableName, pkMap);
+ }
+ return pkMap;
+ }
+
+ private List getCreateValueList(String tableName) {
+ List values = (List) tableValueMap.get(tableName);
+ if (values == null) {
+ values = new ArrayList();
+ tableValueMap.put(tableName, values);
+ }
+ return values;
+ }
+
+ public boolean contains(String tableName, List primaryKey) {
+ return get(tableName, primaryKey) == null ? false : true;
+
+ }
+
+} \ No newline at end of file
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultMetadata.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultMetadata.java
new file mode 100644
index 0000000000..e94f3e3b3b
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultMetadata.java
@@ -0,0 +1,401 @@
+/*
+ * 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.graphbuilder.impl;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.das.rdb.Converter;
+import org.apache.tuscany.das.rdb.config.Column;
+import org.apache.tuscany.das.rdb.config.Config;
+import org.apache.tuscany.das.rdb.config.Table;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper;
+import org.apache.tuscany.das.rdb.impl.ResultSetShape;
+
+import commonj.sdo.Type;
+
+public class ResultMetadata {
+
+ private Map tableToPropertyMap = new HashMap();
+
+ private List typeNames = new ArrayList();
+
+ private List propertyNames = new ArrayList();
+
+ private final ResultSet resultSet;
+
+ private final ResultSetShape resultSetShape;
+
+ private final MappingWrapper configWrapper;
+
+ private Converter[] converters;
+
+ private Map tableToPrimaryKeysMap = new HashMap();
+
+ //JIRA-952
+ public ResultMetadata(ResultSet rs, MappingWrapper cfgWrapper, ResultSetShape shape) throws SQLException {
+
+ this.resultSet = rs;
+ this.configWrapper = cfgWrapper;
+
+ if (shape == null) {
+ this.resultSetShape = new ResultSetShape(rs.getMetaData(), configWrapper.getConfig());
+ } else {
+ this.resultSetShape = shape;
+ }
+
+ this.converters = new Converter[resultSetShape.getColumnCount()];
+
+ Map impliedRelationships = new HashMap();
+ String schemaName = "";
+ String idSpell = null;
+ for (int i = 1; i <= resultSetShape.getColumnCount(); i++) {
+ String tableName = resultSetShape.getTableName(i);
+ schemaName = resultSetShape.getSchemaName(i);
+ if (( tableName == null ) || ( tableName.equals(""))) {
+ throw new RuntimeException("Unable to obtain table information from JDBC. DAS configuration must specify ResultDescriptors");
+ }
+ String typeName = null;
+
+ if(this.configWrapper.getConfig().isDatabaseSchemaNameSupported()){
+ typeName = configWrapper.getTableTypeName(schemaName+"."+tableName);
+ }
+ else{
+ typeName = configWrapper.getTableTypeName(tableName);
+ }
+ String columnName = resultSetShape.getColumnName(i);
+
+ String colName = "";
+ if (columnName.regionMatches(true, columnName.length()-3, "_ID", 0, 3)) {
+ idSpell = columnName.substring(columnName.length()-3, columnName.length());
+ if(this.configWrapper.getConfig().isDatabaseSchemaNameSupported()){
+ colName = schemaName+"."+columnName;
+ impliedRelationships.put(colName, schemaName+"."+tableName);
+ }
+ else{
+ colName = columnName;
+ impliedRelationships.put(colName, tableName);
+ }
+ } else if (columnName.equalsIgnoreCase("ID")) {
+ configWrapper.addImpliedPrimaryKey(schemaName, tableName, columnName);
+ }
+
+ String propertyName = null;
+
+ if(this.configWrapper.getConfig().isDatabaseSchemaNameSupported()){
+ propertyName = configWrapper.getColumnPropertyName(schemaName+"."+tableName, columnName);
+ }
+ else{
+ propertyName = configWrapper.getColumnPropertyName(tableName, columnName);
+ }
+ String converterName = null;
+
+ if(this.configWrapper.getConfig().isDatabaseSchemaNameSupported()){
+ converterName = configWrapper.getConverter(schemaName+"."+tableName, resultSetShape.getColumnName(i));
+ }
+ else{
+ converterName = configWrapper.getConverter(tableName, resultSetShape.getColumnName(i));
+ }
+
+ converters[i - 1] = loadConverter(converterName);
+
+ typeNames.add(typeName);
+ propertyNames.add(propertyName);
+
+ Collection properties = (Collection) tableToPropertyMap.get(typeName);
+ if (properties == null) {
+ properties = new ArrayList();
+ }
+ properties.add(propertyName);
+ tableToPropertyMap.put(typeName, properties);
+
+ }
+
+ //System.out.println("tableToPropertyMap "+tableToPropertyMap);
+ fillTableToPrimaryKeysMap();
+
+ Iterator i = impliedRelationships.keySet().iterator();
+ while (i.hasNext()) {
+ String columnName = (String) i.next();
+ String pkTableName = columnName.substring(0, columnName.indexOf(idSpell));//_id, _Id, _iD, _ID anything
+ String fkTableName = (String) impliedRelationships.get(columnName);
+ List pkTableProperties = (List) tableToPropertyMap.get(pkTableName);
+ if ((pkTableProperties != null) && (pkTableProperties.contains("ID"))) {
+ configWrapper.addImpliedRelationship(pkTableName, fkTableName, columnName);
+ }
+ }
+ // Add any tables defined in the model but not included in the ResultSet
+ // to the list of propertyNames
+ Config model = configWrapper.getConfig();
+ if (model != null) {
+ Iterator tablesFromModel = model.getTable().iterator();
+ while (tablesFromModel.hasNext()) {
+ TableWrapper t = new TableWrapper((Table) tablesFromModel.next());
+ if (tableToPropertyMap.get(t.getTypeName()) == null) {
+ tableToPropertyMap.put(t.getTypeName(), Collections.EMPTY_LIST);
+ }
+ }
+ }
+ }
+
+ //Now fill tableToPrimaryKeysMap.Complete for whichever tables are there in tableToPrimaryKeysMap,
+ //Also case of implied PK and it is not there in SELECT, provide way to still fill it in
+ //tableToPrimaryKeysMap - the column should be present in Config (though not defed as PK)
+ //And consider the classic case, when we assume all columns to be PKs - when no info
+ //in config for table or "all columns"
+ private void fillTableToPrimaryKeysMap(){
+ Iterator itr = tableToPropertyMap.keySet().iterator();
+ while(itr.hasNext()){
+ String curTableName = (String)itr.next();
+ boolean treatAllPKs = false;//flag for, when all cols need to be treated as PKs
+
+ if(tableToPrimaryKeysMap.containsKey(curTableName)){
+ continue;//don't keep refilling same hashset for each ResultMetadata constructor,
+ }
+
+ List columnsForTable = null;
+ if(configWrapper.getTableByTypeName(curTableName) != null) {
+ columnsForTable = configWrapper.getTableByTypeName(curTableName).getColumn();
+ }
+ else if(configWrapper.getTable(curTableName) != null){
+ columnsForTable = configWrapper.getTable(curTableName).getColumn();
+ configWrapper.getTable(curTableName).setTypeName(curTableName);//keep configWrapper consistent with Type info
+ }
+ else{
+ treatAllPKs = true;//can not find table/type, need to consider all columns as PKs
+ }
+
+ if(columnsForTable != null){
+ for(int ii=0; ii<columnsForTable.size(); ii++){
+ Column curCol = (Column)columnsForTable.get(ii);
+
+ if(curCol.isPrimaryKey() || curCol.getColumnName().equalsIgnoreCase("ID")){//need to compare col name
+ //with ID as that is the one from dbms metadata or resul set shape metadata
+ //but when putting in map, need to put property and if not present then column
+ Collection pks = (Collection) tableToPrimaryKeysMap.get(curTableName);
+ if(pks == null){
+ pks = new HashSet();
+ }
+
+ if(curCol.getPropertyName() != null){
+ pks.add(curCol.getPropertyName());
+ }
+ else{
+ pks.add(curCol.getColumnName());
+ curCol.setPropertyName(curCol.getColumnName());//make config consistent
+ if(!((Collection)tableToPropertyMap.get(curTableName)).contains(curCol.getColumnName())){
+ ((Collection)tableToPropertyMap.get(curTableName)).add(curCol.getColumnName());
+ }
+ }
+ tableToPrimaryKeysMap.put(curTableName, pks);
+ }
+ }
+ }
+ else{
+ treatAllPKs = true;//table present in cfg , but no cols
+ }
+
+ if(treatAllPKs){
+ tableToPrimaryKeysMap.put(curTableName, null);//case when all columns are considered PKs
+ }
+ }
+ }
+
+ private Converter loadConverter(String converterName) {
+ if (converterName != null) {
+
+ try {
+ Class converterClazz = Class.forName(converterName, true,
+ Thread.currentThread().getContextClassLoader());
+ if (null != converterClazz) {
+ return (Converter) converterClazz.newInstance();
+ }
+
+ converterClazz = Class.forName(converterName);
+ if (converterClazz != null) {
+ return (Converter) converterClazz.newInstance();
+ }
+ } catch (ClassNotFoundException ex) {
+ throw new RuntimeException(ex);
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(ex);
+ } catch (InstantiationException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ return new DefaultConverter();
+ }
+
+ public String getColumnPropertyName(int i) {
+ return (String) propertyNames.get(i - 1);
+ }
+
+ public String getDatabaseColumnName(int i) {
+ return resultSetShape.getColumnName(i);
+ }
+
+ public String getTableName(String columnName) {
+ return (String) typeNames.get(propertyNames.indexOf(columnName));
+ }
+
+ public int getTableSize(String tableName) {
+ return ((Collection) tableToPropertyMap.get(tableName)).size();
+ }
+
+ public Type getDataType(String columnName) {
+ return resultSetShape.getColumnType(propertyNames.indexOf(columnName));
+ }
+
+ public String getTablePropertyName(int i) {
+ return (String) typeNames.get(i - 1);
+ }
+
+ public Collection getAllTablePropertyNames() {
+ return tableToPropertyMap.keySet();
+ }
+
+ public HashSet getAllPKsForTable(String tableName){
+ if(tableToPrimaryKeysMap.containsKey(tableName))
+ return (HashSet)tableToPrimaryKeysMap.get(tableName);
+ else{
+ HashSet tmpHashSet = new HashSet();
+ tmpHashSet.add("");//case when there were cols in cfg but could not find any PK in it and no ID column in cfg/result set
+ return tmpHashSet;
+ }
+
+ }
+
+ public String toString() {
+
+ StringBuffer result = new StringBuffer(super.toString());
+ result.append(" (Table Names: ");
+ Iterator i = typeNames.iterator();
+ while (i.hasNext()) {
+ String tableName = (String) i.next();
+ result.append(' ');
+ result.append(tableName);
+ result.append(',');
+ }
+
+ result.append(" columnNames: ");
+
+ i = propertyNames.iterator();
+ while (i.hasNext()) {
+ String columnName = (String) i.next();
+ result.append(' ');
+ result.append(columnName);
+ result.append(',');
+ }
+
+ result.append(" mappingModel: ");
+ result.append(this.configWrapper.getConfig());
+
+ result.append(" resultSet: ");
+ result.append(resultSet);
+
+ result.append(" resultSetSize: ");
+ result.append(resultSetShape.getColumnCount());
+ result.append(')');
+ return result.toString();
+
+ }
+
+ /**
+ * @return
+ */
+ public int getNumberOfTables() {
+ return tableToPropertyMap.keySet().size();
+ }
+
+ /**
+ * Return whether the column at the given position is part of a primary key.
+ * If we don't have this information, we assume every column is a primary
+ * key. This results in uniqueness checks using all columns in a table.
+ *
+ * @param i
+ * @return
+ */
+ public boolean isPKColumn(int i) {
+
+ Table t = configWrapper.getTableByTypeName(getTablePropertyName(i));
+ if (t == null) {
+ return true;
+ }
+
+ // If no Columns have been defined, consider every column to be part of
+ // the PK
+ if (t.getColumn().isEmpty()) {
+ return true;
+ }
+
+ Column c = configWrapper.getColumn(t, getDatabaseColumnName(i));
+
+ if (c == null) {
+ return false;
+ }
+
+ if (c.isPrimaryKey()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param i
+ * @return Type
+ */
+ public Type getDataType(int i) {
+ return resultSetShape.getColumnType(i);
+ }
+
+ /**
+ * @param tableName
+ * @return Collection
+ */
+ public Collection getPropertyNames(String tableName) {
+ return (Collection) tableToPropertyMap.get(tableName);
+ }
+
+ public ResultSet getResultSet() {
+ return this.resultSet;
+ }
+
+ public int getResultSetSize() {
+ return resultSetShape.getColumnCount();
+ }
+
+ public boolean isRecursive() {
+ return configWrapper.hasRecursiveRelationships();
+ }
+
+ public Converter getConverter(int i) {
+ return converters[i - 1];
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetProcessor.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetProcessor.java
new file mode 100644
index 0000000000..7722c3c4fd
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetProcessor.java
@@ -0,0 +1,154 @@
+/*
+ * 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.graphbuilder.impl;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Iterator;
+
+import org.apache.log4j.Logger;
+
+import commonj.sdo.DataObject;
+
+/**
+ *
+ * A ResultSetProcessor is used to transform the data in a ResultSet into a set of inter-related EDataObjects.
+ */
+public class ResultSetProcessor {
+ private final Logger logger = Logger.getLogger(ResultSetProcessor.class);
+
+ private TableRegistry registry;
+
+ private GraphBuilderMetadata metadata;
+
+ private final DataObjectMaker doMaker;
+
+ public ResultSetProcessor(DataObject g, GraphBuilderMetadata gbmd) {
+
+ this.metadata = gbmd;
+ if (metadata.getRelationships().size() == 0) {
+ registry = new SingleTableRegistry();
+ } else {
+ registry = new MultiTableRegistry();
+ }
+
+ doMaker = new DataObjectMaker(g);
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug(metadata);
+ }
+
+ }
+
+ /**
+ * Process the ResultSet. For each row in the ResultSet, a
+ *
+ * @link ResultSetRow object will be created to represent the row as a set of EDataObjects. Then,
+ * the relevant relationships will be constructed
+ * between each object in the
+ * @link ResultSetRow.
+ *
+ * @param start
+ * @param end
+ */
+ public void processResults(int start, int end) throws SQLException {
+
+ Iterator i = metadata.getResultMetadata().iterator();
+ while (i.hasNext()) {
+ ResultMetadata resultMetadata = (ResultMetadata) i.next();
+ ResultSet results = resultMetadata.getResultSet();
+
+ processResultSet(results, resultMetadata, start, end);
+
+ // TODO These statements HAVE to be closed or we will have major problems
+ // results.getStatement().close();
+ results.close();
+ }
+
+ }
+
+ private void processResultSet(ResultSet rs, ResultMetadata rsMetadata, int start, int end) throws SQLException {
+
+ if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {
+ while (rs.next() && start < end) {
+ ResultSetRow rsr = new ResultSetRow(rs, rsMetadata);
+ addRowToGraph(rsr, rsMetadata);
+ ++start;
+ }
+ } else {
+ while (rs.absolute(start) && start < end) {
+ ResultSetRow rsr = new ResultSetRow(rs, rsMetadata);
+ addRowToGraph(rsr, rsMetadata);
+ ++start;
+ }
+ }
+ }
+
+ /**
+ * @param row
+ * @param resultMetadata
+ */
+ private void addRowToGraph(ResultSetRow row, ResultMetadata resultMetadata) {
+ RowObjects tableObjects = new RowObjects(metadata, registry);
+ Iterator tables = row.getAllTableData().iterator();
+ while (tables.hasNext()) {
+ TableData rawDataFromRow = (TableData) tables.next();
+
+ if (!rawDataFromRow.hasValidPrimaryKey() ||
+ (rawDataFromRow.hasNullPrimaryKey() && !rawDataFromRow.isTableEmpty())) {//some PK null , but other data present
+ //continue; - need to throw exception as anyway the result will give a wrong impression
+ //when any one table in result set misses PK column or has null value in PK column
+ throw new RuntimeException("Table "+rawDataFromRow.getTableName()+" in query does not include Primary Key "+
+ "column or has null value in it, can not proceed!");
+ }
+
+ String tableName = rawDataFromRow.getTableName();
+ DataObject tableObject = registry.get(tableName, rawDataFromRow.getPrimaryKeyValues());
+ if (tableObject == null
+ && !rawDataFromRow.hasNullPrimaryKey()) {//2nd check for null data in PK,
+ //as TableData.addData() - hasValidPrimaryKey=false is commented for a reason
+ //with this, DataObjs with null PK will not be added to registry and tableObjects
+ tableObject = doMaker.createAndAddDataObject(rawDataFromRow, resultMetadata);
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Putting table " + tableName + " with PK "
+ + rawDataFromRow.getPrimaryKeyValues() + " into registry");
+ }
+
+ registry.put(tableName, rawDataFromRow.getPrimaryKeyValues(), tableObject);
+ }
+ else{
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Not Null tableObject or NULL PK");
+ }
+ }
+
+ if(tableObject != null){
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Do not allow any Null tableObject in tableObjects");
+ }
+ tableObjects.put(tableName, tableObject);
+ }
+ }
+
+ tableObjects.processRelationships();
+
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetRow.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetRow.java
new file mode 100644
index 0000000000..a44713b677
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetRow.java
@@ -0,0 +1,264 @@
+/*
+ * 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.graphbuilder.impl;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+/**
+ *
+ * A ResultSetRow is used to transform a single row of a ResultSet into a set of EDataObjects.
+ */
+public class ResultSetRow {
+ private final Logger logger = Logger.getLogger(ResultSetRow.class);
+
+ private final ResultMetadata metadata;
+
+ private Map tableMap = new HashMap();
+
+ private List allTableData;
+
+ /**
+ * Method ResultSetRow.
+ *
+ * @param rs
+ * A ResultSet positioned on the desired row
+ * @param ePackage
+ * The package used to create EDataObjects
+ */
+ public ResultSetRow(ResultSet rs, ResultMetadata m) throws SQLException {
+ this.metadata = m;
+ if (m.isRecursive()) {
+ processRecursiveRow(rs);
+ } else {
+ processRow(rs);
+ }
+ }
+
+ /**
+ * Processes a single row in the ResultSet Method processRow.
+ *
+ * @param rs
+ */
+ private void processRow(ResultSet rs) throws SQLException {
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("");
+ }
+ for (int i = 1; i <= metadata.getResultSetSize(); i++) {
+ Object data = getObject(rs, i);
+
+ TableData table = getRawData(metadata.getTablePropertyName(i));
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Adding column: " + metadata.getColumnPropertyName(i) + "\tValue: "
+ + data + "\tTable: "
+ + metadata.getTablePropertyName(i));
+ }
+ table.addData(metadata.getColumnPropertyName(i), metadata.isPKColumn(i), data);
+ }
+
+ checkResultSetMissesPK();
+ }
+
+ //get all table names involved in current result set
+ //can not use metadata.getAllTablePropertyNames()
+ //as it gives table names for all tables from Config
+ public Collection getAllTableNamesForRS(){
+ Collection allTableNamesForRS = new HashSet();
+ for (int i = 1; i <= metadata.getResultSetSize(); i++) {
+ allTableNamesForRS.add(metadata.getTablePropertyName(i));
+ }
+ return allTableNamesForRS;
+ }
+
+ //case when result set omits PK column, take care of compound PKs too
+ public void checkResultSetMissesPK(){
+ boolean tableRSHasPK;
+ Collection allTableNames = getAllTableNamesForRS();
+ Iterator itr = allTableNames.iterator();
+ while(itr.hasNext()){
+ tableRSHasPK = false;
+ String currentTableName = (String)itr.next();
+ HashSet pks = metadata.getAllPKsForTable(currentTableName);
+ HashSet pksInRS = new HashSet();
+ for(int j=1; j<=metadata.getResultSetSize(); j++){
+ if(currentTableName.equals(metadata.getTablePropertyName(j)) &&
+ metadata.isPKColumn(j) ){
+ pksInRS.add(metadata.getColumnPropertyName(j));
+ }
+ }
+
+ //if pks null, means its classic case when all cols should be PKs
+ if(pks == null){
+ tableRSHasPK = true;
+ }
+ //case when there were cols in cfg but could not find any PK in it and no ID column in cfg
+ else if(pks != null && pks.size()==1 && pks.contains("")){
+ tableRSHasPK = false;
+ }
+ else if(pks != null && pksInRS.size() == pks.size()){
+ Iterator itr1 = pks.iterator();
+ int indx=0;
+ while(itr1.hasNext()){
+ if(!pksInRS.contains((String)itr1.next())){
+ indx++;
+ }
+ }
+
+ if(indx == 0){
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("has PK TRUE - matched");
+ }
+ tableRSHasPK = true;
+ }else{
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("has PK FALSE- mismatched");
+ }
+ tableRSHasPK = false;
+ }
+ }
+ else{
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("has PK FALSE - rest all cases");
+ }
+ }
+
+ //Default is TRUE(from TableData), so consider only FALSE case
+ if(!tableRSHasPK){
+ TableData table = getRawData(currentTableName);
+ table.setValidPrimaryKey(tableRSHasPK);
+ }
+ }
+
+ //for testing
+ if (this.logger.isDebugEnabled()) {
+ for (int i = 1; i <= metadata.getResultSetSize(); i++) {
+ TableData table = getRawData(metadata.getTablePropertyName(i));
+ this.logger.debug("table "+table.getTableName()+" hasValidPK "+table.hasValidPrimaryKey());
+ }
+ }
+ }
+
+ public void processRecursiveRow(ResultSet rs) throws SQLException {
+ this.allTableData = new ArrayList();
+ int i = 1;
+
+ while (i <= metadata.getResultSetSize()) {
+ TableData table = new TableData(metadata.getTablePropertyName(i));
+ this.allTableData.add(table);
+
+ while ((i <= metadata.getResultSetSize()) && (metadata.isPKColumn(i))) {
+ Object data = getObject(rs, i);
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Adding column: " + metadata.getColumnPropertyName(i)
+ + "\tValue: " + data + "\tTable: "
+ + metadata.getTablePropertyName(i));
+ }
+ table.addData(metadata.getColumnPropertyName(i), true, data);
+ i++;
+ }
+
+ while ((i <= metadata.getResultSetSize()) && (!metadata.isPKColumn(i))) {
+ Object data = getObject(rs, i);
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Adding column: " + metadata.getColumnPropertyName(i)
+ + "\tValue: " + data + "\tTable: "
+ + metadata.getTablePropertyName(i));
+ }
+ table.addData(metadata.getColumnPropertyName(i), false, data);
+ i++;
+ }
+ }
+
+ checkResultSetMissesPK();
+ }
+
+ /**
+ * @param rs
+ * @param metadata
+ * @param i
+ * @return
+ */
+ private Object getObject(ResultSet rs, int i) throws SQLException {
+
+ Object data = rs.getObject(i);
+
+ if (rs.wasNull()) {
+ return null;
+ }
+
+ return metadata.getConverter(i).getPropertyValue(data);
+
+ }
+
+ /**
+ * Returns a HashMap that holds data for the specified table
+ *
+ * @param tableName
+ * The name of the table
+ * @return HashMap
+ */
+ public TableData getTable(String tableName) {
+ return (TableData) tableMap.get(tableName);
+ }
+
+ /**
+ * Returns a HashMap that holds data for the specified table If the HashMap
+ * doesn't exist, it will be created. This is used internally to build
+ * the ResultSetRow, whereas getTable is used externally to retrieve existing table data.
+ *
+ * @param tableName
+ * The name of the table
+ * @return HashMap
+ */
+ private TableData getRawData(String tableName) {
+
+ TableData table = (TableData) tableMap.get(tableName);
+
+ if (table == null) {
+ table = new TableData(tableName);
+ tableMap.put(tableName, table);
+ }
+
+ return table;
+ }
+
+ public List getAllTableData() {
+ if (this.allTableData == null) {
+ this.allTableData = new ArrayList();
+ this.allTableData.addAll(tableMap.values());
+ }
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug(allTableData);
+ }
+
+ return this.allTableData;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/RowObjects.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/RowObjects.java
new file mode 100644
index 0000000000..c7f200cb1e
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/RowObjects.java
@@ -0,0 +1,145 @@
+/*
+ * 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.graphbuilder.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.KeyPair;
+import org.apache.tuscany.das.rdb.config.Relationship;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+
+public class RowObjects {
+ private final Logger logger = Logger.getLogger(RowObjects.class);
+
+ private Map objectsByTableName;
+
+ private List tableObjects;
+
+ private final GraphBuilderMetadata metadata;
+
+ private final TableRegistry registry;
+
+ public RowObjects(GraphBuilderMetadata metadata, TableRegistry registry) {
+ objectsByTableName = new HashMap();
+ tableObjects = new ArrayList();
+ this.metadata = metadata;
+ this.registry = registry;
+ }
+
+ public void put(String key, DataObject value) {
+ objectsByTableName.put(key, value);
+ tableObjects.add(value);
+ }
+
+ public DataObject get(String tablePropertyName) {
+ return (DataObject) objectsByTableName.get(tablePropertyName);
+ }
+
+ void processRelationships() {
+ MappingWrapper wrapper = metadata.getConfigWrapper();
+ if (wrapper.hasRecursiveRelationships()) {
+ processRecursiveRelationships(wrapper);
+ return;
+ }
+
+ Iterator i = metadata.getRelationships().iterator();
+ while (i.hasNext()) {
+ Relationship r = (Relationship) i.next();
+
+ DataObject parentTable = get(wrapper.getTableTypeName(r.getPrimaryKeyTable()));
+ DataObject childTable = get(wrapper.getTableTypeName(r.getForeignKeyTable()));
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Parent table: " + parentTable);
+ this.logger.debug("Child table: " + childTable);
+ }
+ if ((parentTable == null) || (childTable == null)) {
+ continue;
+ }
+
+ Property p = parentTable.getType().getProperty(r.getName());
+ setOrAdd(parentTable, childTable, p);
+
+ }
+ }
+
+ private void processRecursiveRelationships(MappingWrapper wrapper) {
+ Iterator i = tableObjects.iterator();
+ while (i.hasNext()) {
+ DataObject table = (DataObject) i.next();
+
+ Iterator relationships = wrapper.getRelationshipsByChildTable(table.getType().getName()).iterator();
+ while (relationships.hasNext()) {
+ Relationship r = (Relationship) relationships.next();
+
+ DataObject parentTable = findParentTable(table, r, wrapper);
+
+ if (parentTable == null) {
+ continue;
+ }
+
+ Property p = parentTable.getType().getProperty(r.getName());
+ setOrAdd(parentTable, table, p);
+ }
+
+ }
+ }
+
+ private void setOrAdd(DataObject parent, DataObject child, Property p) {
+ if (p.isMany()) {
+ parent.getList(p).add(child);
+ } else {
+ parent.set(p, child);
+ }
+ }
+
+ private DataObject findParentTable(DataObject childTable, Relationship r, MappingWrapper wrapper) {
+
+ List fkValue = new ArrayList();
+ Iterator keyPairs = r.getKeyPair().iterator();
+ while (keyPairs.hasNext()) {
+ KeyPair pair = (KeyPair) keyPairs.next();
+ String childProperty = wrapper.getColumnPropertyName(r.getPrimaryKeyTable(), pair.getForeignKeyColumn());
+
+ Property p = childTable.getType().getProperty(childProperty);
+ fkValue.add(childTable.get(p));
+ }
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Trying to find parent of " + r.getForeignKeyTable() + " with FK " + fkValue);
+ }
+
+ DataObject parentTable = registry.get(r.getPrimaryKeyTable(), fkValue);
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Parent table from registry: " + parentTable);
+ }
+
+ return parentTable;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java
new file mode 100644
index 0000000000..c83b0bbfa2
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java
@@ -0,0 +1,46 @@
+/*
+ * 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.graphbuilder.impl;
+
+import java.util.List;
+
+import commonj.sdo.DataObject;
+
+public class SingleTableRegistry implements TableRegistry {
+
+
+ public SingleTableRegistry() {
+ // Empty Constructor
+ }
+
+ public DataObject get(String tableName, List primaryKey) {
+ return null;
+ }
+
+
+ public void put(String tableName, List primaryKey, DataObject value) {
+ // do nothing
+
+ }
+
+ public boolean contains(String name, List list) {
+ return false;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableData.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableData.java
new file mode 100644
index 0000000000..f74370f003
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableData.java
@@ -0,0 +1,102 @@
+/*
+ * 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.graphbuilder.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+public class TableData {
+ private final Logger logger = Logger.getLogger(TableData.class);
+
+ private Map columnData = new HashMap();
+
+ private List primaryKey = new ArrayList();
+
+ private final String name;
+
+ private boolean hasValidPrimaryKey = true;
+
+ private boolean hasNullPrimaryKey = false;
+
+ public TableData(String tableName) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Creating TableData for table " + tableName);
+ }
+
+ this.name = tableName;
+ }
+
+ public void addData(String columnName, boolean isPrimaryKeyColumn, Object data) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Adding column " + columnName + " with value " + data);
+ }
+
+ if(data != null)
+ columnData.put(columnName, data);
+ if (isPrimaryKeyColumn) {
+ if (data == null) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Column " + columnName + " is a primary key column and is null");
+ }
+ //hasValidPrimaryKey = false; - if uncommented and JIRA-1464, RecursiveTests.testReadEngineParts() will fail
+ }
+ if(data != null){
+ primaryKey.add(data);
+ }
+ else{
+ hasNullPrimaryKey = true;
+ }
+ }
+ }
+
+ public Object getColumnData(String columnName) {
+ return columnData.get(columnName);
+ }
+
+ public String getTableName() {
+ return this.name;
+ }
+
+ /**
+ * @return
+ */
+ public List getPrimaryKeyValues() {
+ return primaryKey;
+ }
+
+ public boolean hasValidPrimaryKey() {
+ return hasValidPrimaryKey;
+ }
+
+ public void setValidPrimaryKey(boolean hasValidPK){
+ this.hasValidPrimaryKey = hasValidPK;
+ }
+
+ public boolean isTableEmpty(){
+ return columnData.keySet().isEmpty();
+ }
+
+ public boolean hasNullPrimaryKey(){
+ return this.hasNullPrimaryKey;
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java
new file mode 100644
index 0000000000..42d8751b03
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java
@@ -0,0 +1,45 @@
+/*
+ * 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.graphbuilder.impl;
+
+import java.util.List;
+
+import commonj.sdo.DataObject;
+
+public interface TableRegistry {
+ /**
+ * Get the table with the specified name and primary key
+ *
+ * @param tableName
+ * @param primaryKey
+ * @return DataObject
+ */
+ DataObject get(String tableName, List primaryKey);
+
+ /**
+ * Add the table with the specified name and primary key
+ *
+ * @param tableName
+ * @param primaryKey
+ * @param value
+ */
+ void put(String tableName, List primaryKey, DataObject value);
+
+ boolean contains(String name, List list);
+} \ No newline at end of file
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/schema/ResultSetTypeMap.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/schema/ResultSetTypeMap.java
new file mode 100644
index 0000000000..35701f88d0
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/schema/ResultSetTypeMap.java
@@ -0,0 +1,137 @@
+/*
+ * 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.graphbuilder.schema;
+
+import java.sql.Types;
+
+import org.apache.tuscany.sdo.SDOPackage;
+
+import commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+
+/**
+ */
+public class ResultSetTypeMap {
+
+ public static final ResultSetTypeMap INSTANCE = new ResultSetTypeMap();
+
+ /**
+ * Constructor for ResultSetTypeMap.
+ */
+ protected ResultSetTypeMap() {
+ // Empty Constructor
+ }
+
+ /**
+ *
+ * @param type
+ * @param isNullable
+ * @return
+ */
+ public Type getEDataType(int type, boolean isNullable) {
+
+ TypeHelper helper = TypeHelper.INSTANCE;
+ SDOPackage.eINSTANCE.eClass();
+ switch (type) {
+
+ case Types.CHAR:
+ case Types.VARCHAR:
+ case Types.LONGVARCHAR:
+ return helper.getType("commonj.sdo", "String");
+
+ case Types.NUMERIC:
+ case Types.DECIMAL:
+ return helper.getType("commonj.sdo", "Decimal");
+
+ case Types.BIT:
+ case Types.BOOLEAN:
+ if (isNullable) {
+ return helper.getType("commonj.sdo", "Boolean");
+ }
+ return helper.getType("commonj.sdo", "boolean");
+
+
+ case Types.TINYINT:
+ case Types.SMALLINT:
+ case Types.INTEGER:
+ if (isNullable) {
+ return helper.getType("commonj.sdo", "IntObject");
+ }
+
+ return helper.getType("commonj.sdo", "Int");
+
+
+ case Types.BIGINT:
+ if (isNullable) {
+ return helper.getType("commonj.sdo", "Long");
+ }
+ return helper.getType("commonj.sdo", "long");
+
+ case Types.REAL:
+ if (isNullable) {
+ return helper.getType("commonj.sdo", "Float");
+ }
+ return helper.getType("commonj.sdo", "float");
+
+
+ case Types.FLOAT:
+ case Types.DOUBLE:
+ if (isNullable) {
+ return helper.getType("commonj.sdo", "Double");
+ }
+ return helper.getType("commonj.sdo", "double");
+
+
+ case Types.BINARY:
+ case Types.VARBINARY:
+ case Types.LONGVARBINARY:
+ return helper.getType("commonj.sdo", "Bytes");
+
+ case Types.DATE:
+ case Types.TIME:
+ case Types.TIMESTAMP:
+ return helper.getType("commonj.sdo", "Date");
+
+ case Types.CLOB:
+ return helper.getType("commonj.sdo", "Object");
+
+ case Types.BLOB:
+ return helper.getType("commonj.sdo", "Bytes");
+
+ case Types.ARRAY:
+ return helper.getType("commonj.sdo", "Object");
+
+ case Types.DISTINCT:
+ case Types.STRUCT:
+ case Types.REF:
+ case Types.DATALINK:
+ case Types.JAVA_OBJECT:
+ return helper.getType("commonj.sdo", "Object");
+
+ default:
+ return helper.getType("commonj.sdo", "Object");
+ }
+
+ }
+
+ public Type getType(int columnType, boolean b) {
+ return getEDataType(columnType, b);
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java
new file mode 100644
index 0000000000..b19aab85e8
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java
@@ -0,0 +1,79 @@
+/*
+ * 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.sql.Connection;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+
+import commonj.sdo.DataObject;
+
+/**
+ *
+ */
+public class ApplyChangesCommandImpl extends BaseCommandImpl {
+
+ private final Logger logger = Logger.getLogger(ApplyChangesCommandImpl.class);
+
+ private ChangeSummarizer summarizer = new ChangeSummarizer();
+
+ public ApplyChangesCommandImpl(MappingWrapper config, Connection connection) {
+ this.configWrapper = config;
+ if (connection != null) {
+ setConnection(connection, config.getConfig());
+ }
+
+ }
+
+ public void setConnection(ConnectionImpl connection) {
+ summarizer.setConnection(connection);
+ }
+
+ public void execute(DataObject root) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Executing ApplyChangesCmd");
+ }
+
+ if (summarizer.getConnection() == null) {
+ throw new RuntimeException("A connection must be provided");
+ }
+
+ if (!root.equals(root.getDataGraph().getRootObject())) {
+ throw new RuntimeException("'root' argument must be the root of the datagraph");
+ }
+
+ summarizer.setMapping(configWrapper);
+
+ Changes changes = summarizer.loadChanges(root);
+
+ boolean success = false;
+ try {
+ changes.execute();
+ success = true;
+ } finally {
+ if (success) {
+ summarizer.getConnection().cleanUp();
+ } else {
+ summarizer.getConnection().errorCleanUp();
+ }
+ }
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java
new file mode 100644
index 0000000000..e6611e0a7f
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java
@@ -0,0 +1,62 @@
+/*
+ * 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.sql.Connection;
+
+import org.apache.tuscany.das.rdb.config.Config;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+
+public abstract class BaseCommandImpl {
+ protected MappingWrapper configWrapper = new MappingWrapper();
+
+ //when no config in method params, useGetGeneratedKeys will default to True
+ //as DBMS metadata method is not reliable in all cases
+ public void setConnection(Connection connection) {
+ setConnection(new ConnectionImpl(connection));
+ }
+
+ public void setConnection(Connection connection, Config config) {
+ boolean managed = true;
+ String generatedKeysSupported = null;
+
+ if (config != null){
+ if(config.getConnectionInfo() != null) {
+ managed = config.getConnectionInfo().isManagedtx();
+ }
+
+ generatedKeysSupported = config.getGeneratedKeysSupported();
+
+ setConnection(connection, managed, generatedKeysSupported);
+ }
+ else{
+ setConnection(connection);
+ }
+ }
+
+ public void setConnection(Connection connection, boolean manageTransaction, String generatedKeysSupported) {
+ ConnectionImpl c = new ConnectionImpl(connection);
+ c.setManageTransactions(manageTransaction);
+ c.setGeneratedKeysSupported(generatedKeysSupported);
+ setConnection(c);
+ }
+
+ public abstract void setConnection(ConnectionImpl c);
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java
new file mode 100644
index 0000000000..c348eae54e
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java
@@ -0,0 +1,177 @@
+/*
+ * 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 org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.Create;
+import org.apache.tuscany.das.rdb.config.Delete;
+import org.apache.tuscany.das.rdb.config.Table;
+import org.apache.tuscany.das.rdb.config.Update;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper;
+import org.apache.tuscany.das.rdb.generator.impl.DeleteGenerator;
+import org.apache.tuscany.das.rdb.generator.impl.InsertGenerator;
+import org.apache.tuscany.das.rdb.generator.impl.UpdateGenerator;
+
+import commonj.sdo.DataObject;
+
+public class ChangeFactory {
+ private final Logger logger = Logger.getLogger(ChangeFactory.class);
+
+ private InsertCommandImpl createCommand;
+
+ private UpdateCommandImpl updateCommand;
+
+ private DeleteCommandImpl deleteCommand;
+
+ private final MappingWrapper mapping;
+
+ private final ConnectionImpl connection;
+
+ public ChangeFactory(MappingWrapper mapping, ConnectionImpl connection) {
+ this.mapping = mapping;
+ this.connection = connection;
+ }
+
+ public void setCreateCommand(InsertCommandImpl cmd) {
+ createCommand = cmd;
+ }
+
+ public void setUpdateCommand(UpdateCommandImpl cmd) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Setting Update Command to " + cmd);
+ }
+
+ updateCommand = cmd;
+ }
+
+ public void setDeleteCommand(DeleteCommandImpl cmd) {
+ deleteCommand = cmd;
+ }
+
+ ChangeOperation createUpdateOperation(DataObject changedObject, String propagatedID) {
+ return new UpdateOperation(getUpdateCommand(changedObject), changedObject, propagatedID);
+ }
+
+ ChangeOperation createUpdateOperation(DataObject changedObject) {
+ return createUpdateOperation(changedObject, null);
+ }
+
+ ChangeOperation createDeleteOperation(DataObject changedObject) {
+ return new DeleteOperation(getDeleteCommand(changedObject), changedObject);
+ }
+
+ ChangeOperation createInsertOperation(DataObject changedObject, String propagatedID) {
+ return new CreateOperation(getCreateCommand(changedObject), changedObject, propagatedID);
+ }
+
+ private InsertCommandImpl getCreateCommand(DataObject changedObject) {
+
+ if (createCommand == null) {
+ Table table = mapping.getTableByTypeName(changedObject.getType().getName());
+ if (table == null) {
+ if (changedObject.getType().getProperty("ID") != null) {
+ // If the table is not defined in the config, assume it has a primary key of "ID"
+ mapping.addPrimaryKey(changedObject.getType().getName() + ".ID");
+ table = mapping.getTableByTypeName(changedObject.getType().getName());
+ } else {
+ throw new RuntimeException("Table " + changedObject.getType().getName()
+ + " was changed in the DataGraph but is not present in the Config");
+ }
+ }
+
+ Create create = table.getCreate();
+
+ if (create == null) {
+ createCommand = InsertGenerator.INSTANCE.getInsertCommand(mapping, changedObject, table);
+ } else {
+ createCommand = new InsertCommandImpl(create);
+ }
+ createCommand.setConnection(connection);
+ createCommand.configWrapper = mapping;
+ }
+ return createCommand;
+ }
+
+ private DeleteCommandImpl getDeleteCommand(DataObject changedObject) {
+
+ if (deleteCommand == null) {
+ Table table = mapping.getTableByTypeName(changedObject.getType().getName());
+ if (table == null) {
+ if (changedObject.getType().getProperty("ID") != null) {
+ // If the table is not defined in the config, assume it has a primary key of "ID"
+ mapping.addPrimaryKey(changedObject.getType().getName() + ".ID");
+ table = mapping.getTableByTypeName(changedObject.getType().getName());
+ } else {
+ throw new RuntimeException("Table " + changedObject.getType().getName()
+ + " was changed in the DataGraph but is not present in the Config");
+ }
+ }
+
+ Delete delete = table.getDelete();
+
+ if (delete == null) {
+ deleteCommand = DeleteGenerator.INSTANCE.getDeleteCommand(mapping, table);//JIRA-952
+ } else {
+ deleteCommand = new DeleteCommandImpl(delete);
+ }
+ deleteCommand.setConnection(connection);
+ deleteCommand.configWrapper = mapping;
+ }
+ return deleteCommand;
+ }
+
+ private UpdateCommandImpl getUpdateCommand(DataObject changedObject) {
+
+ Table table = mapping.getTableByTypeName(changedObject.getType().getName());
+ if (table == null) {
+ if (changedObject.getType().getProperty("ID") != null) {
+ mapping.addPrimaryKey(changedObject.getType().getName() + ".ID");
+ table = mapping.getTableByTypeName(changedObject.getType().getName());
+ } else {
+ throw new RuntimeException("Table " + changedObject.getType().getName()
+ + " was changed in the DataGraph but is not present in the Config");
+ }
+ }
+ Update update = table.getUpdate();
+ if (update == null) {
+ updateCommand = UpdateGenerator.INSTANCE.getUpdateCommand(mapping, changedObject, table);
+ } else {
+ TableWrapper t = new TableWrapper(table);
+ if (t.getCollisionColumn() != null) {
+ updateCommand = new OptimisticWriteCommandImpl(update);
+ } else {
+ updateCommand = new UpdateCommandImpl(update);
+ }
+ }
+ updateCommand.setConnection(connection);
+ updateCommand.configWrapper = mapping;
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Returning updateCommand: " + updateCommand);
+ }
+
+ return updateCommand;
+ }
+
+ public MappingWrapper getConfig() {
+ return this.mapping;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java
new file mode 100644
index 0000000000..b222c18177
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java
@@ -0,0 +1,87 @@
+/*
+ * 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.util.Iterator;
+
+import org.apache.log4j.Logger;
+
+import commonj.sdo.DataObject;
+
+/**
+ */
+public abstract class ChangeOperation {
+ protected DatabaseObject dObject;
+
+ protected String propagatedID;
+
+ private final Logger logger = Logger.getLogger(ChangeOperation.class);
+
+ private final WriteCommandImpl writeCommand;
+
+ private boolean isInsert;
+
+
+ public ChangeOperation(DeleteCommandImpl command) {
+ writeCommand = command;
+ }
+
+ public ChangeOperation(InsertCommandImpl command, DataObject changedObject) {
+ writeCommand = command;
+ dObject = new DatabaseObject(command.getMappingModel(), changedObject);
+ this.isInsert = true;
+ }
+
+ public ChangeOperation(UpdateCommandImpl command, DataObject changedObject) {
+ writeCommand = command;
+ dObject = new DatabaseObject(command.getMappingModel(), changedObject);
+ }
+
+ public void execute() {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Executing change operation");
+ }
+
+ Iterator i = writeCommand.getParameters().iterator();
+ while (i.hasNext()) {
+ ParameterExtendedImpl parm = (ParameterExtendedImpl) i.next();
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("setting " + parm.getName() + " to " + dObject.get(parm.getName()));
+ }
+
+ parm.setValue(dObject.get(parm.getName()));
+ }
+
+ writeCommand.basicExecute();
+
+ if (isInsert && (propagatedID != null)) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Propagating key " + propagatedID);
+ }
+ int id = writeCommand.getGeneratedKey();
+ dObject.setPropagatedID(propagatedID, id);
+ }
+ }
+
+ public String getTableName() {
+ return dObject.getTableName();
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java
new file mode 100644
index 0000000000..9858e4c972
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java
@@ -0,0 +1,241 @@
+/*
+ * 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.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.Command;
+import org.apache.tuscany.das.rdb.config.Column;
+import org.apache.tuscany.das.rdb.config.Relationship;
+import org.apache.tuscany.das.rdb.config.Table;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+import org.apache.tuscany.das.rdb.config.wrapper.RelationshipWrapper;
+import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper;
+import org.apache.tuscany.das.rdb.util.CollectionsUtil;
+import org.apache.tuscany.sdo.impl.ChangeSummaryImpl;
+
+import commonj.sdo.ChangeSummary;
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+
+public class ChangeSummarizer {
+
+ private final Logger logger = Logger.getLogger(ChangeSummarizer.class);
+
+ private Changes changes = new Changes();
+
+ private FactoryRegistry registry;
+
+ private MappingWrapper mapping = new MappingWrapper();
+
+ private ConnectionImpl connection;
+
+ private Map generatedKeys = new HashMap();
+
+ public ChangeSummarizer() {
+ // Empty Constructor
+ }
+
+ public Changes loadChanges(DataObject root) {
+ ChangeSummary changeSummary = root.getDataGraph().getChangeSummary();
+ if (changeSummary.isLogging()) {
+ ((ChangeSummaryImpl) changeSummary).summarize();
+ }
+
+ List changedObjects = changeSummary.getChangedDataObjects();
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("List of changed objects contains " + changedObjects.size() + " object(s)");
+ }
+
+ changes.setInsertOrder(mapping.getInsertOrder());
+ changes.setDeleteOrder(mapping.getDeleteOrder());
+
+ Iterator i = changedObjects.iterator();
+ while (i.hasNext()) {
+ DataObject o = (DataObject) i.next();
+
+ if (!(o.equals(root))) {
+ createChange(changeSummary, o);
+ }
+ }
+
+ return changes;
+ }
+
+ public void createChange(ChangeSummary changeSummary, DataObject changedObject) {
+
+ if (changeSummary.isCreated(changedObject)) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Change is a create");
+ }
+ if (!changeSummary.isDeleted(changedObject)) {
+ ChangeFactory factory = getRegistry().getFactory(changedObject.getType());
+ String propagatedID = (String) generatedKeys.get(changedObject.getType().getName());
+ changes.addInsert(factory.createInsertOperation(changedObject, propagatedID));
+ }
+ } else if (changeSummary.isDeleted(changedObject)) {
+ ChangeFactory factory = getRegistry().getFactory(changedObject.getType());
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Change is a delete");
+ }
+ changes.addDelete(factory.createDeleteOperation(changedObject));
+ } else {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Change is a modify");
+ }
+ List attrList = changeSummary.getOldValues(changedObject);
+ if (hasAttributeChange(attrList)) {
+ ChangeFactory factory = getRegistry().getFactory(changedObject.getType());
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Attribute Change for " + changedObject.getType().getName());
+ }
+ String propagatedID = (String) generatedKeys.get(changedObject.getType().getName());
+ changes.addUpdate(factory.createUpdateOperation(changedObject, propagatedID));
+ } else {
+ List values = changeSummary.getOldValues(changedObject);
+ Iterator i = values.iterator();
+ while (i.hasNext()) {
+ ChangeSummary.Setting setting = (ChangeSummary.Setting) i.next();
+ if (!setting.getProperty().getType().isDataType()) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Reference change for " + changedObject.getType().getName());
+ }
+ Property ref = setting.getProperty();
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug(ref.getName());
+ }
+ if (hasState(ref, changedObject)) {
+ ChangeFactory factory = getRegistry().getFactory(changedObject.getType());
+ changes.addUpdate(factory.createUpdateOperation(changedObject));
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ private boolean hasState(Property ref, DataObject changedObject) {
+ if (ref.getOpposite().isMany()) {
+ return true;
+ }
+
+ MappingWrapper mw = this.mapping;
+ if (mw.getConfig() == null) {
+ mw = registry.getFactory(changedObject.getType()).getConfig();
+ }
+ if (mw.getConfig() == null) {
+ return false;
+ }
+
+ Relationship rel = mw.getRelationshipByReference(ref);
+
+ if (!rel.isMany()) {
+ if (rel.isKeyRestricted()) {
+ throw new RuntimeException("Can not modify a one to one relationship that is key restricted");
+ }
+ // This is a one-one relationship
+ Table t = mapping.getTableByTypeName(changedObject.getType().getName());
+ TableWrapper tw = new TableWrapper(t);
+ RelationshipWrapper rw = new RelationshipWrapper(rel);
+ if ((rel.getForeignKeyTable().equals(t.getTableName()))
+ && (CollectionsUtil.disjoint(tw.getPrimaryKeyProperties(), rw.getForeignKeys()))) {
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+
+ private boolean hasAttributeChange(List theChanges) {
+ Iterator i = theChanges.iterator();
+ while (i.hasNext()) {
+ ChangeSummary.Setting setting = (ChangeSummary.Setting) i.next();
+ if (setting.getProperty().getType().isDataType()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void addCreateCommand(Type type, Command cmd) {
+ ChangeFactory cf = getRegistry().getFactory(type);
+ cf.setCreateCommand((InsertCommandImpl) cmd);
+ ((CommandImpl) cmd).setConnection(connection);
+ }
+
+ public void addUpdateCommand(Type type, Command cmd) {
+ ChangeFactory cf = getRegistry().getFactory(type);
+ cf.setUpdateCommand((UpdateCommandImpl) cmd);
+ ((CommandImpl) cmd).setConnection(connection);
+ }
+
+ public void addDeleteCommand(Type type, Command cmd) {
+ ChangeFactory cf = getRegistry().getFactory(type);
+ cf.setDeleteCommand((DeleteCommandImpl) cmd);
+ ((CommandImpl) cmd).setConnection(connection);
+
+ }
+
+ private FactoryRegistry getRegistry() {
+ if (this.registry == null) {
+ this.registry = new FactoryRegistry(mapping, connection);
+ }
+ return this.registry;
+ }
+
+ public void setConnection(ConnectionImpl connection) {
+ this.connection = connection;
+ }
+
+ public void setMapping(MappingWrapper map) {
+ this.mapping = map;
+
+ if (mapping.getConfig() == null) {
+ return;
+ }
+
+ Iterator i = mapping.getConfig().getTable().iterator();
+ while (i.hasNext()) {
+ Table t = (Table) i.next();
+ Iterator columns = t.getColumn().iterator();
+ while (columns.hasNext()) {
+ Column c = (Column) columns.next();
+ if (c.isPrimaryKey() && c.isGenerated()) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("adding generated key " + t.getTableName() + "." + c.getColumnName());
+ }
+
+ generatedKeys.put(t.getTableName(), c.getColumnName());
+ }
+ }
+ }
+ }
+
+ public ConnectionImpl getConnection() {
+ return this.connection;
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java
new file mode 100644
index 0000000000..2cc5f906c9
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java
@@ -0,0 +1,82 @@
+/*
+ * 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.util.Iterator;
+import java.util.List;
+
+/**
+ * Manages a set of graph-change operations. This simple implementaiton can be
+ * replaced with a version that provides R/I sorting
+ *
+ */
+public class Changes {
+
+ private InsertList inserts = new InsertList();
+
+ private UpdateList updates = new UpdateList();
+
+ private DeleteList deletes = new DeleteList();
+
+ public void addInsert(ChangeOperation c) {
+ inserts.add(c);
+ }
+
+ public void addUpdate(ChangeOperation c) {
+ updates.add(c);
+ }
+
+ public void addDelete(ChangeOperation c) {
+ deletes.add(c);
+ }
+
+ /**
+ * Execute all my change
+ */
+ public void execute() {
+
+ Iterator i = inserts.getSortedList().iterator();
+ while (i.hasNext()) {
+ ChangeOperation c = (ChangeOperation) i.next();
+ c.execute();
+ }
+
+ i = updates.getSortedList().iterator();
+ while (i.hasNext()) {
+ ChangeOperation c = (ChangeOperation) i.next();
+ c.execute();
+ }
+
+ i = deletes.getSortedList().iterator();
+ while (i.hasNext()) {
+ ChangeOperation c = (ChangeOperation) i.next();
+ c.execute();
+ }
+
+ }
+
+ public void setInsertOrder(List insertOrder) {
+ inserts.setOrder(insertOrder);
+ }
+
+ public void setDeleteOrder(List deleteOrder) {
+ deletes.setOrder(deleteOrder);
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CollisionParameter.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CollisionParameter.java
new file mode 100644
index 0000000000..48ff2ab57a
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CollisionParameter.java
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+public class CollisionParameter extends ParameterExtendedImpl {
+
+ private boolean isSet;
+
+ public void setValue(Object value) {
+ if (!isSet) {
+ this.value = value;
+ isSet = true;
+ }
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java
new file mode 100644
index 0000000000..0efabc4adb
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java
@@ -0,0 +1,178 @@
+/*
+ * 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.InputStream;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tuscany.das.rdb.Command;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.XSDHelper;
+
+public abstract class CommandImpl extends BaseCommandImpl implements Command {
+
+ protected Statement statement;
+
+ protected ParametersExtendedImpl parameters = new ParametersExtendedImpl();
+
+ protected ResultSetShape resultSetShape;
+
+ public CommandImpl(String sqlString) {
+ statement = new Statement(sqlString);
+
+ try {
+ URL url = getClass().getResource("/xml/sdoJava.xsd");
+ if (url == null) {
+ throw new RuntimeException("Could not find resource: xml/sdoJava.xsd");
+ }
+
+ InputStream inputStream = url.openStream();
+ XSDHelper.INSTANCE.define(inputStream, url.toString());
+ inputStream.close();
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+
+ }
+
+ public CommandImpl(org.apache.tuscany.das.rdb.config.Command command) {
+ this(command.getSQL());
+
+ if(command.getParameter() != null && command.getParameter().size() > 0) {
+ Iterator itr = command.getParameter().iterator();
+ int index = 1;
+ while(itr.hasNext()){
+ org.apache.tuscany.das.rdb.config.impl.ParameterImpl param = (org.apache.tuscany.das.rdb.config.impl.ParameterImpl)itr.next();
+ if(param.getIndex() <= 0){
+ param.setIndex(index);
+ index++;
+ }
+ ParameterExtendedImpl paramExt = new ParameterExtendedImpl(param);
+ addToParameters(paramExt);
+ }
+ }
+ }
+
+ private void addToParameters(ParameterExtendedImpl paramExt) {
+ this.parameters.getParameter().add(paramExt);
+ if(paramExt.getDirection().equals(ParameterExtendedImpl.IN)){
+ parameters.getInParameters().add(paramExt);
+ }
+ else{
+ parameters.getOutParameters().add(paramExt);
+ }
+ }
+
+ public abstract void execute();
+
+ public abstract DataObject executeQuery();
+
+ public void setParameter(int index, Object value) {
+ ParameterExtendedImpl param = parameters.getParameter(index);
+ if(param != null){
+ param.setValue(value);
+ return;
+ }
+
+ param = new ParameterExtendedImpl();
+ param.setIndex(index);
+ param.setValue(value);
+ param.setDirection(ParameterExtendedImpl.IN);
+ parameters.getParameter().add(param);
+ parameters.getInParameters().add(param);
+ }
+
+ public void addParameter(ParameterExtendedImpl param) {
+ //eliminate/replace duplicate params, index is filled, so can check it for duplicate
+ ParameterExtendedImpl paramExt = parameters.getParameter(param.getIndex());
+ if(paramExt != null)
+ paramExt = new ParameterExtendedImpl(param);
+
+ paramExt = parameters.getParameter(param.getIndex(), param.getDirection());
+ if(paramExt != null){
+ paramExt = new ParameterExtendedImpl(param);
+ return;
+ }
+
+ addToParameters(param);
+ }
+
+ public List getParameters() {
+ return parameters.getParameter();
+ }
+
+ public Object getParameter(int index) {
+ return parameters.getParameter(index).getValue();
+ }
+
+ public void setConnection(ConnectionImpl connection) {
+ statement.setConnection(connection);
+ }
+
+ protected ConnectionImpl getConnection() {
+ return statement.getConnection();
+ }
+
+ /*
+ * The default impl is to throw an exception. This is overridden by InsertCommandImpl
+ */
+ public int getGeneratedKey() {
+
+ throw new RuntimeException("This method is only valid for insert commands");
+ }
+
+ public void close() {
+ statement.close();
+ }
+
+ //default direction IN assumed
+ public void setParameter(String name, Object value) {
+ ParameterExtendedImpl param = parameters.getParameter(name);
+ if(param != null){
+ param.setValue(value);
+ return;
+ }
+
+ param = new ParameterExtendedImpl();
+ param.setIndex(parameters.getParameter().size()+1);
+ param.setName(name);
+ param.setValue(value);
+ param.setDirection(ParameterExtendedImpl.IN);
+ parameters.getParameter().add(param);
+ parameters.getInParameters().add(param);
+ }
+
+ //default direction IN assumed
+ public Object getParameter(String name) {
+ Iterator itr = this.parameters.getInParameters().iterator();
+ while(itr.hasNext()){
+ ParameterExtendedImpl param = ((ParameterExtendedImpl)itr.next());
+
+ if(param.getName() != null && param.getName().equalsIgnoreCase(name)){
+ return param.value;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java
new file mode 100644
index 0000000000..24341797b6
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java
@@ -0,0 +1,154 @@
+/*
+ * 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.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.log4j.Logger;
+
+public class ConnectionImpl {
+
+ private final Logger logger = Logger.getLogger(ConnectionImpl.class);
+
+ private Connection connection;
+
+ private boolean managingTransaction = true;
+
+ private String generatedKeysSupported = null;
+
+ public ConnectionImpl(Connection connection) {
+ this.connection = connection;
+
+ try {
+ if (connection.getAutoCommit()) {
+ throw new RuntimeException("AutoCommit must be off");
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public Connection getJDBCConnection() {
+ return connection;
+ }
+
+ public String getGeneratedKeysSupported() {
+ return this.generatedKeysSupported;
+ }
+
+ public void setGeneratedKeysSupported(String useGetGeneratedKeys){
+ this.generatedKeysSupported = useGetGeneratedKeys;
+ }
+
+ public boolean isGeneratedKeysSupported() {
+ try{
+ if(this.generatedKeysSupported == null){
+ DatabaseMetaData dbmsMetadata = this.connection.getMetaData();
+ boolean supportsGetGeneratedKeys = dbmsMetadata.supportsGetGeneratedKeys();
+ if(supportsGetGeneratedKeys){
+ this.generatedKeysSupported = "true";
+ }
+ //currently DERBY partially supports this feature and thus returns FALSE,
+ //this hardcoding is needed as the partial support is enough for DAS
+ //we can remove this later, when DERBY change the behaviour of it's "supportsGetGeneratedKeys"
+ else if(dbmsMetadata.getDatabaseProductName().indexOf("Derby") > 0){
+ this.generatedKeysSupported = "true";
+ }
+ else{
+ this.generatedKeysSupported = "false";
+ }
+ }
+ }catch(Exception e){//can be from supportsGetGeneratedKeys or due to absense of supportsGetGeneratedKeys
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("exception setiing useGetGeneratedKeys false");
+ }
+ this.generatedKeysSupported = "false";
+ }
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("returning useGetGeneratedKeys():"+ this.generatedKeysSupported);
+ }
+ return Boolean.parseBoolean(this.generatedKeysSupported);
+ }
+
+ public void cleanUp() {
+ try {
+ if (managingTransaction) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Committing Transaction");
+ }
+ connection.commit();
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void errorCleanUp() {
+ try {
+ if (managingTransaction) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Rolling back Transaction");
+ }
+ connection.rollback();
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public PreparedStatement prepareStatement(String queryString, String[] returnKeys) throws SQLException {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Preparing Statement: " + queryString);
+ this.logger.debug("Boolean value for use gen key: " + this.generatedKeysSupported);
+ }
+
+ if (isGeneratedKeysSupported()) {
+ return connection.prepareStatement(queryString, Statement.RETURN_GENERATED_KEYS);
+ } else if (returnKeys.length > 0) {
+ return connection.prepareStatement(queryString, returnKeys);
+ }
+
+ return connection.prepareStatement(queryString);
+ }
+
+ public PreparedStatement preparePagedStatement(String queryString) throws SQLException {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Preparing Statement: " + queryString);
+ }
+
+ return connection.prepareStatement(queryString, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ }
+
+ public void setManageTransactions(boolean manageTransactions) {
+ managingTransaction = manageTransactions;
+
+ }
+
+ public CallableStatement prepareCall(String queryString) throws SQLException {
+ return connection.prepareCall(queryString);
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java
new file mode 100644
index 0000000000..0163f96686
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java
@@ -0,0 +1,30 @@
+/*
+ * 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 commonj.sdo.DataObject;
+
+public class CreateOperation extends ChangeOperation {
+
+ public CreateOperation(InsertCommandImpl command, DataObject changedObject, String id) {
+ super(command, changedObject);
+ this.propagatedID = id;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java
new file mode 100644
index 0000000000..ba80b3bcb5
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java
@@ -0,0 +1,50 @@
+/*
+ * 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.InputStream;
+import java.sql.Connection;
+
+import org.apache.tuscany.das.rdb.DAS;
+import org.apache.tuscany.das.rdb.DASFactory;
+import org.apache.tuscany.das.rdb.config.Config;
+
+public class DASFactoryImpl implements DASFactory {
+
+ public DAS createDAS(InputStream configStream) {
+ return new DASImpl(configStream);
+ }
+
+ public DAS createDAS(Config config) {
+ return new DASImpl(config);
+ }
+
+ public DAS createDAS(InputStream configStream, Connection connection) {
+ return new DASImpl(configStream, connection);
+ }
+
+ public DAS createDAS(Config config, Connection connection) {
+ return new DASImpl(config, connection);
+ }
+
+ public DAS createDAS(Connection connection) {
+ return new DASImpl(connection);
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java
new file mode 100644
index 0000000000..55e0df0bd2
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java
@@ -0,0 +1,313 @@
+/*
+ * 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.InputStream;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
+import org.apache.tuscany.das.rdb.Command;
+import org.apache.tuscany.das.rdb.DAS;
+import org.apache.tuscany.das.rdb.config.Config;
+import org.apache.tuscany.das.rdb.config.ConfigFactory;
+import org.apache.tuscany.das.rdb.config.ConnectionInfo;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+import org.apache.tuscany.das.rdb.exception.DataSourceInitializationException;
+import org.apache.tuscany.das.rdb.util.ConfigUtil;
+
+import commonj.sdo.DataObject;
+
+/**
+ * An ConfiguredCommandFactory produces instances of Command and ApplyChangesCommand. This
+ * factory is initialized with a configuration that defines
+ * the commands it produces.
+ *
+ */
+public class DASImpl implements DAS {
+
+ private MappingWrapper configWrapper;
+
+ private Connection connection;
+
+ private Map commands = new HashMap();
+
+ public DASImpl(InputStream stream) {
+ this(ConfigUtil.loadConfig(stream));
+
+ }
+
+ public DASImpl(Config inConfig) {
+ Config cfg = inConfig;
+ if (cfg == null) {
+ cfg = ConfigFactory.INSTANCE.createConfig();
+ }
+ this.configWrapper = new MappingWrapper(cfg);
+
+ Iterator i = configWrapper.getConfig().getCommand().iterator();
+ while (i.hasNext()) {
+ org.apache.tuscany.das.rdb.config.Command commandConfig =
+ (org.apache.tuscany.das.rdb.config.Command) i.next();
+ String kind = commandConfig.getKind();
+ if (kind.equalsIgnoreCase("select")) {
+ commands.put(commandConfig.getName(), new ReadCommandImpl(commandConfig, configWrapper, commandConfig.getResultDescriptor()));
+ } else if (kind.equalsIgnoreCase("update")) {
+ commands.put(commandConfig.getName(), new UpdateCommandImpl(commandConfig));
+ } else if (kind.equalsIgnoreCase("insert")) {
+ commands.put(commandConfig.getName(), new InsertCommandImpl(commandConfig, new String[0]));
+ } else if (kind.equalsIgnoreCase("delete")) {
+ commands.put(commandConfig.getName(), new DeleteCommandImpl(commandConfig));
+ } else if (kind.equalsIgnoreCase("procedure")) {
+ commands.put(commandConfig.getName(), new SPCommandImpl(commandConfig.getSQL(), configWrapper, commandConfig.getParameter()));
+ } else {
+ throw new RuntimeException("Invalid kind of command: " + kind);
+ }
+
+ }
+
+ }
+
+ public DASImpl(Config inConfig, Connection inConnection) {
+ this(inConfig);
+ setConnection(inConnection);
+ }
+
+ public DASImpl(InputStream configStream, Connection inConnection) {
+ this(ConfigUtil.loadConfig(configStream), inConnection);
+ }
+
+ public DASImpl(Connection inConnection) {
+ this(ConfigFactory.INSTANCE.createConfig());
+ setConnection(inConnection);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.das.rdb.CommandGroup#getApplyChangesCommand()
+ */
+ public ApplyChangesCommandImpl getApplyChangesCommand() {
+ ApplyChangesCommandImpl cmd = new ApplyChangesCommandImpl(configWrapper, getConnection());
+ return cmd;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.das.rdb.CommandGroup#getCommand(java.lang.String)
+ */
+ public Command getCommand(String name) {
+ if (!commands.containsKey(name)) {
+ throw new RuntimeException("CommandGroup has no command named: " + name);
+ }
+ CommandImpl cmd = (CommandImpl) commands.get(name);
+ cmd.setConnection(getConnection(), configWrapper.getConfig());
+ return cmd;
+ }
+
+ public void setConnection(Connection connection) {
+ this.connection = connection;
+ }
+
+ public Connection getConnection() {
+ if (connection == null) {
+ initializeConnection();
+ }
+ return connection;
+ }
+
+ private void initializeConnection() {
+ Config config = configWrapper.getConfig();
+ if (config == null || config.getConnectionInfo() == null ||
+ (config.getConnectionInfo().getDataSource() == null && config.getConnectionInfo().getConnectionProperties() == null)) {
+ throw new RuntimeException("No connection has been provided and no data source has been specified");
+ }
+
+ if(config.getConnectionInfo().getDataSource() != null && config.getConnectionInfo().getConnectionProperties() != null){
+ throw new RuntimeException("Use either dataSource or ConnectionProperties. Can't use both !");
+ }
+
+ ConnectionInfo connectionInfo = configWrapper.getConfig().getConnectionInfo();
+ if(config.getConnectionInfo().getConnectionProperties() != null){
+ initializeDriverManagerConnection(connectionInfo);
+ }else{
+ initializeDatasourceConnection(connectionInfo);
+ }
+
+ }
+
+ /**
+ * Initializes a DB connection on a managed environmet (e.g inside Tomcat)
+ */
+ private void initializeDatasourceConnection(ConnectionInfo connectionInfo){
+ Connection connection = null;
+
+ InitialContext ctx;
+ try {
+ ctx = new InitialContext();
+ } catch (NamingException e) {
+ throw new RuntimeException(e);
+ }
+ try {
+ DataSource ds = (DataSource) ctx.lookup(connectionInfo.getDataSource());
+ try {
+ connection = ds.getConnection();
+ if (connection == null) {
+ throw new RuntimeException("Could not obtain a Connection from DataSource");
+ }
+ connection.setAutoCommit(false);
+ setConnection(connection);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ } catch (NamingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Initialize a DB connection on a J2SE environment
+ * For more info, see http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/drivermanager.html
+ */
+ private void initializeDriverManagerConnection(ConnectionInfo connectionInfo) {
+
+ Connection connection = null;
+
+ if (connectionInfo.getConnectionProperties() == null) {
+ throw new DataSourceInitializationException("No existing context and no connection properties");
+ }
+
+ if (connectionInfo.getConnectionProperties().getDriverClass() == null) {
+ throw new DataSourceInitializationException("No jdbc driver class specified!");
+ }
+
+ try {
+ //initialize driver and register it with DriverManager
+ Class.forName(connectionInfo.getConnectionProperties().getDriverClass());
+
+ //prepare to initialize connection
+ String databaseUrl = connectionInfo.getConnectionProperties().getDatabaseURL();
+ String userName = connectionInfo.getConnectionProperties().getUserName();
+ String userPassword = connectionInfo.getConnectionProperties().getPassword();
+ int loginTimeout = connectionInfo.getConnectionProperties().getLoginTimeout();
+
+ DriverManager.setLoginTimeout(loginTimeout);
+ if( (userName == null || userName.length() ==0) && (userPassword == null || userPassword.length()==0) ){
+ //no username or password suplied
+ connection = DriverManager.getConnection(databaseUrl);
+ }else{
+ connection = DriverManager.getConnection(databaseUrl, userName, userPassword);
+ }
+
+ if(connection == null){
+ throw new DataSourceInitializationException("Error initializing connection : null");
+ }
+
+ connection.setAutoCommit(false);
+ setConnection(connection);
+
+
+ }catch(ClassNotFoundException cnf){
+ throw new DataSourceInitializationException("JDBC Driver '" + connectionInfo.getConnectionProperties().getDriverClass() + "' not found", cnf);
+ }catch(SQLException sqle){
+ throw new DataSourceInitializationException(sqle.getMessage(), sqle);
+ }
+
+ }
+
+ public void releaseResources() {
+
+ if (managingConnections()) {
+ closeConnection();
+ }
+ }
+
+ private void closeConnection() {
+ if (connection != null) {
+ try {
+ connection.close();
+ connection = null;
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * If the config has connection properties then we are "managing" the connection via DataSource
+ */
+ private boolean managingConnections() {
+
+ if (configWrapper.getConfig().getConnectionInfo().getDataSource() == null) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ public Command createCommand(String sql) {
+ return baseCreateCommand(sql, this.configWrapper);
+ }
+
+ public Command createCommand(String sql, Config config) {
+ return baseCreateCommand(sql, new MappingWrapper(config));
+ }
+
+ private Command baseCreateCommand(String inSql, MappingWrapper config) {
+ CommandImpl returnCmd = null;
+ String sql = inSql.trim(); // Remove leading white space
+ char firstChar = Character.toUpperCase(sql.charAt(0));
+ switch (firstChar) {
+ case 'S':
+ returnCmd = new ReadCommandImpl(sql, config, null);
+ break;
+ case 'I':
+ returnCmd = new InsertCommandImpl(sql, new String[0]);
+ break;
+ case 'U':
+ returnCmd = new UpdateCommandImpl(sql);
+ break;
+ case 'D':
+ returnCmd = new DeleteCommandImpl(sql);
+ break;
+ case '{':
+ returnCmd = new SPCommandImpl(sql, config, Collections.EMPTY_LIST);
+ break;
+ default:
+ throw new RuntimeException("SQL => " + sql + " is not valid");
+ }
+
+ returnCmd.setConnection(getConnection(), config.getConfig());
+ return returnCmd;
+ }
+
+ public void applyChanges(DataObject root) {
+ getApplyChangesCommand().execute(root);
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java
new file mode 100644
index 0000000000..110fd1bd38
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java
@@ -0,0 +1,202 @@
+/*
+ * 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.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.Column;
+import org.apache.tuscany.das.rdb.config.Config;
+import org.apache.tuscany.das.rdb.config.KeyPair;
+import org.apache.tuscany.das.rdb.config.Relationship;
+import org.apache.tuscany.das.rdb.config.Table;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+
+/**
+ * DatabaseObject wraps DataObject. If a field is an FK field, it will return the value from the parent.
+ *
+ *
+ */
+public class DatabaseObject {
+
+ private final Logger logger = Logger.getLogger(DatabaseObject.class);
+
+ private final MappingWrapper mappingWrapper;
+
+ private final DataObject dataObject;
+
+ private Property parentReference;
+
+ private Map keyMappings = new HashMap();
+
+ public DatabaseObject(Config model, DataObject changedObject) {
+ this.mappingWrapper = new MappingWrapper(model);
+ this.dataObject = changedObject;
+ initialize();
+ }
+
+ // Initialize Key Mappings
+ private void initialize() {
+ if (mappingWrapper.getConfig() != null) {
+ List relationships = mappingWrapper.getConfig().getRelationship();
+ Iterator i = relationships.iterator();
+ while (i.hasNext()) {
+ Relationship r = (Relationship) i.next();
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Initializing relationship: " + r.getName());
+ this.logger.debug("r.getForeignKeyTable():"+r.getForeignKeyTable());
+ this.logger.debug("getTypeName():"+getTypeName());
+ }
+
+ if (r.getForeignKeyTable().equals(getTypeName())) {
+ List pairs = r.getKeyPair();
+ Iterator iter = pairs.iterator();
+ while (iter.hasNext()) {
+ KeyPair pair = (KeyPair) iter.next();
+ keyMappings.put(pair.getForeignKeyColumn(), r);
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Putting key pair: " + pair.getPrimaryKeyColumn()+","+pair.getForeignKeyColumn());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public Object get(String parameter) {
+ if (isPartOfPrimaryKey(parameter)) {
+ return dataObject.get(parameter);
+ }
+
+ Relationship r = (Relationship) keyMappings.get(parameter);
+ if (r == null) {
+ return dataObject.get(parameter);
+ }
+
+ //JIRA-952
+ Table tbl = this.mappingWrapper.getTable(r.getPrimaryKeyTable());
+ Property parentRef = null;
+ if(tbl == null){
+ //this is case when config file is not present and
+ //ConfigHelper helper = new ConfigHelper(); is used
+ parentRef = getParentReference(r.getPrimaryKeyTable());
+ }
+ else{
+ //other cases, its better to use typeName as r.getPrimaryKeyTable()
+ //gives tableName and tableName and typeName can be different
+ //and SDO looks for typeName and not tableName.
+ parentRef = getParentReference((new TableWrapper(tbl)).getTypeName());
+ }
+
+ DataObject parent = dataObject.getDataObject(parentRef);
+
+ if (parent == null) {
+ return null;
+ }
+ String parentKey = getParentKey(r, parameter);
+ return parent.get(parentKey);
+
+ }
+
+ private String getParentKey(Relationship r, String parameter) {
+ List keyPairs = r.getKeyPair();
+ Iterator i = keyPairs.iterator();
+ while (i.hasNext()) {
+ KeyPair pair = (KeyPair) i.next();
+ if (pair.getForeignKeyColumn().equals(parameter)) {
+ return pair.getPrimaryKeyColumn();
+ }
+ }
+ return null;
+ }
+
+ public Property getParentReference(String parentName) {
+ if (this.parentReference == null) {
+ Iterator i = dataObject.getType().getProperties().iterator();
+ while (i.hasNext()) {
+ Property ref = (Property) i.next();
+ if ((!ref.getType().isDataType()) && (ref.getType().getName().equals(parentName))) {
+ this.parentReference = ref;
+ }
+ }
+ }
+ return this.parentReference;
+ }
+
+ //JIRA-952
+ public String getTableName() {
+ if (mappingWrapper.getConfig() != null) {
+
+ if(mappingWrapper.getConfig().isDatabaseSchemaNameSupported()){
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("DatabaseObject.getTableName:(schemaName.tableName) " +
+ mappingWrapper.getTableByTypeName(getTypeName()).getSchemaName()+"."+
+ mappingWrapper.getTableByTypeName(getTypeName()).getTableName());
+ }
+
+ return (mappingWrapper.getTableByTypeName(getTypeName()).getSchemaName()+"."+
+ mappingWrapper.getTableByTypeName(getTypeName()).getTableName());
+ }
+ else{
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("DatabaseObject.getTableName: " + mappingWrapper.getTableByTypeName(getTypeName()).getTableName());
+ }
+
+ return mappingWrapper.getTableByTypeName(getTypeName()).getTableName();
+ }
+ }
+ return null;
+ }
+
+ public String getTypeName() {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("DatabaseObject.getTypeName: " + dataObject.getType().getName());
+ }
+ return dataObject.getType().getName();
+ }
+
+ public void setPropagatedID(String propagatedID, int id) {
+ dataObject.setInt(propagatedID, id);
+ }
+
+ private boolean isPartOfPrimaryKey(String parameter) {
+ if (mappingWrapper.getConfig() == null) {
+ return false;
+ }
+
+ Table t = mappingWrapper.getTable(getTableName());
+ if (t == null) {
+ return false;
+ }
+ Column c = mappingWrapper.getColumnByPropertyName(t, parameter);
+ if (c == null) {
+ return false;
+ }
+
+ return c.isPrimaryKey();
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java
new file mode 100644
index 0000000000..ca85569272
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java
@@ -0,0 +1,37 @@
+/*
+ * 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 org.apache.tuscany.das.rdb.config.Delete;
+
+public class DeleteCommandImpl extends WriteCommandImpl {
+ public DeleteCommandImpl(org.apache.tuscany.das.rdb.config.Command command) {
+ super(command);
+ }
+
+ public DeleteCommandImpl(String sqlString) {
+ super(sqlString);
+ }
+
+ public DeleteCommandImpl(Delete delete) {
+ super(delete.getSql());
+ this.addParameters(delete.getParameters());
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java
new file mode 100644
index 0000000000..feb7e31411
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java
@@ -0,0 +1,77 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * DeleteList will sort delete operations so that child objects are deleted before their parents
+ *
+ *
+ */
+public class DeleteList {
+
+ private Map opsByTableName = new HashMap();
+
+ private List order;
+
+ private List deleteOperations = new ArrayList();
+
+ public DeleteList() {
+ super();
+ }
+
+ public void add(ChangeOperation op) {
+ if ((order.size() == 0) || (op.getTableName() == null)) {
+ deleteOperations.add(op);
+ } else {
+ String name = op.getTableName();
+ List ops = (List) opsByTableName.get(name);
+ if (ops == null) {
+ ops = new ArrayList();
+ }
+ ops.add(op);
+ opsByTableName.put(name, ops);
+ }
+ }
+
+ public Collection getSortedList() {
+ if ((order.size() > 0) && (opsByTableName.keySet().size() > 0)) {
+ Iterator i = this.order.iterator();
+ while (i.hasNext()) {
+ String name = (String) i.next();
+ if (opsByTableName.get(name) != null) {
+ deleteOperations.addAll((Collection) opsByTableName.get(name));
+ }
+ }
+ }
+
+ return deleteOperations;
+ }
+
+ public void setOrder(List deleteOrder) {
+ this.order = deleteOrder;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java
new file mode 100644
index 0000000000..52935599c1
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.apache.tuscany.das.rdb.util.DataObjectUtil;
+
+import commonj.sdo.DataObject;
+
+public class DeleteOperation extends ChangeOperation {
+
+ /**
+ * @param command
+ * @param changedObject
+ * Objects deleted from the graph have lost their "settings" and must be restored
+ */
+ public DeleteOperation(DeleteCommandImpl command, DataObject changedObject) {
+ super(command);
+ this.dObject = new DatabaseObject(command.getMappingModel(), DataObjectUtil.getRestoredCopy(changedObject));
+
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java
new file mode 100644
index 0000000000..bb148635c8
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java
@@ -0,0 +1,57 @@
+/*
+ * 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.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+
+import commonj.sdo.Type;
+
+public class FactoryRegistry {
+
+ private final Logger logger = Logger.getLogger(FactoryRegistry.class);
+
+ private Map registry = new HashMap();
+
+ private final MappingWrapper mapping;
+
+ private final ConnectionImpl connection;
+
+ public FactoryRegistry(MappingWrapper mapping, ConnectionImpl connection) {
+ this.mapping = mapping;
+ this.connection = connection;
+ }
+
+ public ChangeFactory getFactory(Type type) {
+ ChangeFactory factory = (ChangeFactory) registry.get(type);
+ if (factory == null) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Creating new ChangeFactory for type " + type.getName());
+ }
+
+ factory = new ChangeFactory(mapping, connection);
+ registry.put(type, factory);
+ }
+ return factory;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java
new file mode 100644
index 0000000000..61967475bd
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java
@@ -0,0 +1,75 @@
+/*
+ * 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.sql.SQLException;
+
+import org.apache.tuscany.das.rdb.config.Create;
+
+public class InsertCommandImpl extends WriteCommandImpl {
+
+ private String[] keys;
+
+ public InsertCommandImpl(org.apache.tuscany.das.rdb.config.Command command, String[] generatedKeys) {
+ super(command);
+ keys = generatedKeys;
+ }
+
+ public InsertCommandImpl(String sqlString, String[] generatedKeys) {
+ super(sqlString);
+ keys = generatedKeys;
+ }
+
+ public InsertCommandImpl(Create create) {
+ super(create.getSql());
+ this.addParameters(create.getParameters());
+ this.keys = new String[0];
+ }
+
+ public void execute() {
+
+ boolean success = false;
+ try {
+ statement.executeUpdate(parameters, keys);
+ success = true;
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (success) {
+ statement.getConnection().cleanUp();
+ } else {
+ statement.getConnection().errorCleanUp();
+ }
+ }
+
+ }
+
+ public int getGeneratedKey() {
+ try {
+ Integer key = statement.getGeneratedKey();
+ if(key != null)
+ return key.intValue();
+ else
+ throw new RuntimeException("Could not obtain generated key!");
+ } catch (SQLException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java
new file mode 100644
index 0000000000..e61ccfe21e
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java
@@ -0,0 +1,95 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+/**
+ * InsertList will sort ChangeOperation objects so that parents are inserted before children
+ *
+ *
+ */
+public class InsertList {
+ private final Logger logger = Logger.getLogger(InsertList.class);
+
+ private Map opsByTableName = new HashMap();
+
+ private List insertOperations = new ArrayList();
+
+ private List order;
+
+ public void add(ChangeOperation op) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Adding insert operation ");
+ }
+
+ // If nothing has been added yet, or this is no ordering, simply
+ // add the operation to the list
+ if ((order.size() == 0) || (op.getTableName() == null)) {
+ insertOperations.add(op);
+ } else {
+ String name = op.getTableName();
+ List ops = (List) opsByTableName.get(name);
+ if (ops == null) {
+ ops = new ArrayList();
+ }
+
+ ops.add(op);
+ opsByTableName.put(name, ops);
+ }
+ }
+
+ public Collection getSortedList() {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Getting sorted insert list");
+ }
+
+ if ((order.size() > 0) && opsByTableName.keySet().size() > 0) {
+ Iterator i = this.order.iterator();
+ while (i.hasNext()) {
+ String name = (String) i.next();
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Adding operations for table " + name);
+ }
+
+ // A null here means a table is in the config but hasn't been changed here
+ if (opsByTableName.get(name) != null) {
+ insertOperations.addAll((Collection) opsByTableName.get(name));
+ }
+ }
+ }
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Returning " + insertOperations.size() + " insert operations");
+ }
+
+ return insertOperations;
+ }
+
+ public void setOrder(List insertOrder) {
+ this.order = insertOrder;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java
new file mode 100644
index 0000000000..f2f3ccdd79
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java
@@ -0,0 +1,39 @@
+/*
+ * 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.math.BigDecimal;
+
+public class ManagedParameterImpl extends ParameterExtendedImpl {
+
+ public void setValue(Object oldValue) {
+ this.value = updateValue(oldValue);
+ }
+
+ private Object updateValue(Object oldValue) {
+ if (oldValue instanceof Integer) {
+ return new Integer(((Integer) oldValue).intValue() + 1);
+ } else if (oldValue instanceof BigDecimal) {
+ return ((BigDecimal) oldValue).add(new BigDecimal(1));
+ } else {
+ throw new RuntimeException("Unsupported type for managed column: " + oldValue.getClass().getName());
+ }
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java
new file mode 100644
index 0000000000..0a5f6951e9
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java
@@ -0,0 +1,48 @@
+/*
+ * 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.sql.SQLException;
+
+import org.apache.tuscany.das.rdb.config.Update;
+import org.apache.tuscany.das.rdb.exception.OptimisticConcurrencyException;
+
+public class OptimisticWriteCommandImpl extends UpdateCommandImpl {
+
+ public OptimisticWriteCommandImpl(String sqlString) {
+ super(sqlString);
+ }
+
+ public OptimisticWriteCommandImpl(Update update) {
+ super(update);
+ addParameters(update.getParameters());
+ }
+
+ public void basicExecute() {
+ try {
+ int rowsAffected = statement.executeUpdate(parameters);
+ if (rowsAffected == 0) {
+ throw new OptimisticConcurrencyException("An update collision occurred");
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java
new file mode 100644
index 0000000000..27b653763b
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java
@@ -0,0 +1,69 @@
+/*
+ * 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 org.apache.tuscany.das.rdb.Command;
+import org.apache.tuscany.das.rdb.Pager;
+
+import commonj.sdo.DataObject;
+
+public class PagerImpl implements Pager {
+
+ private final ReadCommandImpl command;
+
+ private final int size;
+
+ private int idx = 1;
+
+ public PagerImpl(Command command, int size) {
+ this.command = (ReadCommandImpl) command;
+ this.command.enablePaging();
+ this.size = size;
+ }
+
+ public DataObject next() {
+ int start = idx;
+ int end = idx + size;
+ idx += size;
+ command.setStartRow(start);
+ command.setEndRow(end);
+ return command.executeQuery();
+ }
+
+ public DataObject getPage(int page) {
+ int end = (page * size) + 1;
+ int start = end - size;
+ idx = end;
+ command.setStartRow(start);
+ command.setEndRow(end);
+ return command.executeQuery();
+ }
+
+ public DataObject previous() {
+ int start = idx - (2 * size);
+ if (start < 1) {
+ start = 1;
+ }
+ int end = start + size;
+ idx = end;
+ command.setStartRow(start);
+ command.setEndRow(end);
+ return command.executeQuery();
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterExtendedImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterExtendedImpl.java
new file mode 100644
index 0000000000..ccb42edc78
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterExtendedImpl.java
@@ -0,0 +1,98 @@
+/*
+ * 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 org.apache.tuscany.das.rdb.Converter;
+import org.apache.tuscany.das.rdb.config.impl.ParameterImpl;
+import commonj.sdo.Type;
+
+public class ParameterExtendedImpl extends ParameterImpl{
+ /**
+ * Value for "Direction" that indicates that a parameter is soley for input.
+ */
+ static final String IN = "IN";
+
+ /**
+ * Value for "Direction" that indicates that a parameter is soley for output.
+ * Out parameters only apply to Stored Procedures
+ */
+ static final String OUT = "OUT";
+
+ /**
+ * Value for "Direction" that indicates that a parameter is for both input and output.
+ * In-out parameters only apply to stored procedures
+ */
+ static final String IN_OUT = "IN_OUT";
+
+ private Type type;
+
+ protected Object value;
+
+ private Converter converter;
+
+ public ParameterExtendedImpl() {
+ super();
+ this.direction = IN;
+ }
+
+ public ParameterExtendedImpl(org.apache.tuscany.das.rdb.config.impl.ParameterImpl parameterImpl) {
+ this.columnType = parameterImpl.getColumnType();
+ this.direction = parameterImpl.getDirection();
+ this.index = parameterImpl.getIndex();
+ this.name = parameterImpl.getName();
+ }
+
+ public void setType(Type type) {
+ this.type = type;
+ }
+
+ public Type getType() {
+ return this.type;
+ }
+
+ public void setColumnType(String newColumnType) {
+ super.setColumnType(newColumnType);
+ if(newColumnType != null){
+ String arg0 = newColumnType.substring(0, newColumnType.lastIndexOf("."));
+ String arg1 = newColumnType.substring(newColumnType.lastIndexOf(".")+1);
+ this.type = SDODataTypes.TYPE_HELPER.getType(arg0, arg1);
+ }
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ public Object getValue() {
+ if (getConverter() != null) {
+ return getConverter().getColumnValue(this.value);
+ }
+
+ return this.value;
+ }
+
+ public void setConverter(Converter converter) {
+ this.converter = converter;
+ }
+
+ public Converter getConverter() {
+ return this.converter;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java
new file mode 100644
index 0000000000..3e23faf069
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java
@@ -0,0 +1,120 @@
+/*
+ * 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 org.apache.tuscany.das.rdb.Converter;
+
+import commonj.sdo.Type;
+
+public class ParameterImpl {
+
+ /**
+ * Value for "Direction" that indicates that a parameter is soley for input.
+ */
+ static final int IN = 1;
+
+ /**
+ * Value for "Direction" that indicates that a parameter is soley for output.
+ * Out parameters only apply to Stored Procedures
+ */
+ static final int OUT = 2;
+
+ /**
+ * Value for "Direction" that indicates that a parameter is for both input and output.
+ * In-out parameters only apply to stored procedures
+ */
+ static final int IN_OUT = 3;
+
+ protected Object value;
+
+ private int index;
+
+ private Type type;
+
+ private String name;
+
+ private int direction = IN;
+
+ private Converter converter;
+
+
+ public ParameterImpl() {
+ super();
+ }
+
+ public ParameterImpl(int index) {
+ this.index = index;
+ }
+
+ public void setType(Type type) {
+ this.type = type;
+ }
+
+ public void setIndex(int index) {
+ if (index == 0) {
+ throw new RuntimeException("Index of zero not allowed");
+ }
+ this.index = index;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ public void setDirection(int direction) {
+ this.direction = direction;
+ }
+
+ public Type getType() {
+ return this.type;
+ }
+
+ public int getIndex() {
+ return this.index;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public Object getValue() {
+ if (getConverter() != null) {
+ return getConverter().getColumnValue(this.value);
+ }
+
+ return this.value;
+ }
+
+ public int getDirection() {
+ return this.direction;
+ }
+
+ public void setConverter(Converter converter) {
+ this.converter = converter;
+ }
+
+ public Converter getConverter() {
+ return this.converter;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java
new file mode 100644
index 0000000000..bebfba9ce9
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java
@@ -0,0 +1,113 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import commonj.sdo.Type;
+
+public class Parameters {
+ private final Logger logger = Logger.getLogger(Parameters.class);
+
+ private List parameters = new ArrayList();
+
+ private List inParams = new ArrayList();
+
+ private List outParams = new ArrayList();
+
+ public Parameters() {
+ super();
+ }
+
+ public ParameterImpl get(int index) {
+ return (ParameterImpl) parameters.get(index);
+ }
+
+ public List outParams() {
+ return outParams;
+ }
+
+ public List inParams() {
+ return inParams;
+ }
+
+ private void addParameter(ParameterImpl param) {
+ if (param.getDirection() == ParameterImpl.IN) {
+ inParams.add(param);
+ } else if ((param.getDirection() == ParameterImpl.OUT) || (param.getDirection() == ParameterImpl.IN_OUT)) {
+ outParams.add(param);
+ }
+
+ this.parameters.add(param);
+ }
+
+ public void add(ParameterImpl param) {
+ addParameter(param);
+ }
+
+ public ParameterImpl findOrCreateParameterWithIndex(int index, int direction, Type sdoType) {
+ Iterator i = parameters.iterator();
+ while (i.hasNext()) {
+ ParameterImpl param = (ParameterImpl) i.next();
+
+ if (param.getIndex() == index) {
+ return param;
+ }
+ }
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Creating new parameter with index " + index);
+ }
+
+ ParameterImpl newParam = new ParameterImpl(index);
+ newParam.setDirection(direction);
+ newParam.setType(sdoType);
+ addParameter(newParam);
+ return newParam;
+ }
+
+ public List parameterList() {
+ return parameters;
+ }
+
+ public ParameterImpl findOrCreateParameterWithIndex(int index) {
+ return findOrCreateParameterWithIndex(index, ParameterImpl.IN, null);
+ }
+
+ public void setParameter(int index, Object value) {
+ ParameterImpl param = findOrCreateParameterWithIndex(index);
+ param.setValue(value);
+ }
+
+ public ParameterImpl parameterWithIndex(int index) {
+ Iterator i = parameters.iterator();
+ while (i.hasNext()) {
+ ParameterImpl param = (ParameterImpl) i.next();
+
+ if (param.getIndex() == index) {
+ return param;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParametersExtendedImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParametersExtendedImpl.java
new file mode 100644
index 0000000000..190695ae14
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParametersExtendedImpl.java
@@ -0,0 +1,189 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.Parameters;
+import org.apache.tuscany.das.rdb.config.impl.ParameterImpl;
+import org.apache.tuscany.das.rdb.config.impl.ParametersImpl;
+
+import commonj.sdo.Type;
+
+public class ParametersExtendedImpl extends ParametersImpl{
+ private final Logger logger = Logger.getLogger(ParametersExtendedImpl.class);
+ private List inParams = new ArrayList();
+
+ private List outParams = new ArrayList();
+
+ public ParametersExtendedImpl(){
+
+ }
+
+ public ParametersExtendedImpl(List paramsList) {
+ if(this.parameter == null){
+ this.parameter = new ArrayList();
+ }
+ if(paramsList != null){
+ for(int i=0; i<paramsList.size(); i++){
+ ParameterImpl paramImpl = (ParameterImpl)paramsList.get(i);
+ ParameterExtendedImpl paramExtImpl = new ParameterExtendedImpl();
+ paramExtImpl.setColumnType(paramImpl.getColumnType());
+ paramExtImpl.setIndex(paramImpl.getIndex());
+ paramExtImpl.setName(paramImpl.getName());
+ paramExtImpl.setDirection(paramImpl.getDirection());
+ this.parameter.add(paramExtImpl);
+ }
+ }
+ }
+
+ public ParametersExtendedImpl(Parameters params) {
+ this(params.getParameter());
+ }
+
+ public List getOutParameters() {
+ return outParams;
+ }
+
+ public List getInParameters() {
+ return inParams;
+ }
+
+ public ParameterExtendedImpl getParameter(int index) {
+ if(this.getParameter() == null || this.getParameter().isEmpty())
+ return null;
+
+ Iterator itr = this.getParameter().iterator();
+ while(itr.hasNext()){
+ ParameterExtendedImpl curParam = (ParameterExtendedImpl)itr.next();
+ if(curParam.getIndex() == index){
+ return curParam;
+ }
+ }
+ return null;
+ }
+
+ public ParameterExtendedImpl getParameter(int index, String direction) {
+ if(direction.equals(ParameterExtendedImpl.IN)) {
+ Iterator itr = this.inParams.iterator();
+ while(itr.hasNext()){
+ ParameterExtendedImpl curParam = (ParameterExtendedImpl)itr.next();
+ if(curParam.getIndex() == index){
+ return curParam;
+ }
+ }
+ }
+ else {
+ Iterator itr = this.outParams.iterator();
+ while(itr.hasNext()){
+ ParameterExtendedImpl curParam = (ParameterExtendedImpl)itr.next();
+ if(curParam.getIndex() == index){
+ return curParam;
+ }
+ }
+ }
+ return null;
+ }
+
+ private ParameterExtendedImpl getNamedParameter(List params, String name){
+ if(params == null)
+ return null;
+ for(int i=0; i<params.size(); i++){
+ if( ((ParameterExtendedImpl)params.get(i)).getName().equals(name)){
+ return (ParameterExtendedImpl)params.get(i);
+ }
+ }
+ return null;
+ }
+
+ public ParameterExtendedImpl getParameter(String name) {
+ return getNamedParameter(this.getParameter(), name);
+ }
+
+ public ParameterExtendedImpl getParameter(String name, String direction) {
+ if(direction.equals(ParameterExtendedImpl.IN))
+ return getNamedParameter(this.inParams, name);
+ else
+ return getNamedParameter(this.outParams, name);
+ }
+
+ public ParameterExtendedImpl findOrCreateParameterWithIndex(int index, String direction, Type sdoType) {
+ if(this.parameter == null){
+ this.parameter = new ArrayList();
+ }
+ Iterator i = this.parameter.iterator();
+ while (i.hasNext()) {
+ ParameterExtendedImpl param = (ParameterExtendedImpl) i.next();
+
+ if (param.getIndex() == index) {
+ return param;
+ }
+ }
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Creating new parameter with index " + index);
+ }
+
+ ParameterExtendedImpl newParam = new ParameterExtendedImpl();
+ newParam.setIndex(index);
+ newParam.setDirection(direction);
+ newParam.setType(sdoType);
+ newParam.setColumnType(SDODataTypeHelper.columnTypeForSDOType(sdoType));
+ this.getParameter().add(newParam);
+ if(!direction.equals(ParameterExtendedImpl.IN)){
+ this.getOutParameters().add(newParam);
+ }
+ else{
+ this.getInParameters().add(newParam);
+ }
+ return newParam;
+ }
+
+ /**maintain compatibility with parameters="name1 name2 " from config
+ *
+ * @param parameters
+ */
+ public static ArrayList getParameters(String parameters) {
+ StringTokenizer tokenizer = new StringTokenizer(parameters);
+ ArrayList paramExtList = new ArrayList();
+ for (int idx = 1; tokenizer.hasMoreTokens(); idx++) {
+ ParameterExtendedImpl p = new ParameterExtendedImpl();
+ p.setName(tokenizer.nextToken());
+ p.setIndex(idx);
+ p.setDirection(ParameterExtendedImpl.IN);
+ paramExtList.add(p);
+ }
+ return paramExtList;
+ }
+
+ public void addParameters(List paramExtList){
+ for(int i=0; i<paramExtList.size(); i++){
+ ParameterExtendedImpl curParam = (ParameterExtendedImpl)paramExtList.get(i);
+ this.getParameter().add(curParam);
+ if(curParam.getDirection().equals(ParameterExtendedImpl.IN))
+ this.getInParameters().add(paramExtList.get(i));
+ else
+ this.getOutParameters().add(paramExtList.get(i));
+ }
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java
new file mode 100644
index 0000000000..608ed6122a
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java
@@ -0,0 +1,338 @@
+/*
+ * 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.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
+
+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 {
+ List results = statement.executeQuery(parameters);
+ success = true;
+ 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();
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java
new file mode 100644
index 0000000000..a9744d42b9
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java
@@ -0,0 +1,161 @@
+/*
+ * 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.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.tuscany.das.rdb.config.Config;
+import org.apache.tuscany.das.rdb.config.ResultDescriptor;
+import org.apache.tuscany.das.rdb.graphbuilder.schema.ResultSetTypeMap;
+
+import commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+
+/**
+ * Describes the structure of the result set returned from
+ * execution of a SELECT statement. This description is typcially
+ * not required since the shape can be retreived from the JDBC
+ * ResultSetMetadata. However, some platforms such as Oracle do not
+ * support fully suport ResultSetMedata.
+ * <p>
+ * There may also be a performance boost when using this interface.
+ *
+ *
+ */
+public class ResultSetShape {
+
+ private final String[] columns;
+
+ private final String[] tables;
+
+ private final Type[] types;
+
+ private final String[] schema;//JIRA-952
+ //JIRA-952
+ public ResultSetShape(ResultSetMetaData metadata, Config model) throws SQLException {
+ columns = new String[metadata.getColumnCount()];
+ tables = new String[metadata.getColumnCount()];
+ types = new Type[metadata.getColumnCount()];
+ schema = new String[metadata.getColumnCount()];
+
+ ResultSetTypeMap typeMap = ResultSetTypeMap.INSTANCE;
+ for (int i = 1; i <= metadata.getColumnCount(); i++) {
+ if(model.isDatabaseSchemaNameSupported()){
+ if(metadata.getSchemaName(i) != null && !metadata.getSchemaName(i).equals("")){
+ //tables[i - 1] = metadata.getSchemaName(i)+"."+metadata.getTableName(i);
+ tables[i - 1] = metadata.getTableName(i);
+ schema[i - 1] = metadata.getSchemaName(i);
+ }
+ else{
+ tables[i - 1] = metadata.getTableName(i);
+ schema[i - 1] = "";
+ }
+ }
+ else{
+ tables[i - 1] = metadata.getTableName(i);
+ schema[i - 1] = "";
+ }
+ columns[i - 1] = metadata.getColumnName(i);
+ types[i - 1] = typeMap.getType(metadata.getColumnType(i), true);
+ }
+ }
+
+ //JIRA-952
+ protected ResultSetShape(List resultDescriptor, Config model) {
+ TypeHelper helper = TypeHelper.INSTANCE;
+ int size = resultDescriptor.size();
+ columns = new String[size];
+ tables = new String[size];
+ types = new Type[size];
+ schema = new String[size];
+
+ for (int i = 0; i < size; i++) {
+ ResultDescriptor desc = (ResultDescriptor) resultDescriptor.get(i);
+ if(model.isDatabaseSchemaNameSupported()){
+ if(desc.getSchemaName() != null && !desc.getSchemaName().equals("")){
+ tables[i] = desc.getTableName();
+ schema[i] = desc.getSchemaName();
+ }else{
+ tables[i] = desc.getTableName();
+ schema[i] = "";
+ }
+
+ }else{
+ tables[i] = desc.getTableName();
+ schema[i] = "";
+ }
+ columns[i] = desc.getColumnName();
+
+ int idx = desc.getColumnType().lastIndexOf('.');
+ String uri = desc.getColumnType().substring(0, idx);
+ String typeName = desc.getColumnType().substring(idx + 1);
+
+ types[i] = helper.getType(uri, typeName);
+ if (types[i] == null) {
+ throw new RuntimeException("Could not find type " + desc.getColumnType()
+ + " for column " + desc.getColumnName());
+ }
+ }
+
+ }
+
+ public int getColumnCount() {
+ return columns.length;
+ }
+
+ public String getTableName(int i) {
+ return tables[i - 1];
+ }
+
+ //JIRA-952
+ public String getSchemaName(int i) {
+ return schema[i - 1];
+ }
+ public String getColumnName(int i) {
+ return columns[i - 1];
+ }
+
+ public Type getColumnType(int i) {
+ return types[i - 1];
+ }
+
+ public String toString() {
+ StringBuffer result = new StringBuffer();
+ result.append(" column/table/schema/type: ");
+ for (int i = 0; i < columns.length; i++) {
+ result.append(columns[i]);
+ result.append('\t');
+ result.append(tables[i]);
+ result.append('\t');
+ result.append(schema[i]);
+ result.append('\t');
+ if (types[i] == null) {
+ result.append("null");
+ } else {
+ result.append(types[i].getName());
+ }
+ result.append('\n');
+ }
+
+ return result.toString();
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java
new file mode 100644
index 0000000000..8afd37fa05
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java
@@ -0,0 +1,187 @@
+/*
+ * 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.sql.Types;
+
+import commonj.sdo.Type;
+
+public final class SDODataTypeHelper {
+
+ private SDODataTypeHelper() {
+
+ }
+
+ public static String columnTypeForSDOType(Type sdoType){
+ if(sdoType == null){
+ return null;
+ }
+
+ if (sdoType == SDODataTypes.BOOLEAN) {
+ return SDODataTypes.BOOLEAN_STR;
+ } else if (sdoType == SDODataTypes.STRING) {
+ return SDODataTypes.STRING_STR;
+ } else if (sdoType == SDODataTypes.BYTE) {
+ return SDODataTypes.BYTE_STR;
+ } else if (sdoType == SDODataTypes.BYTES) {
+ return SDODataTypes.BYTES_STR;
+ } else if (sdoType == SDODataTypes.CHARACTER) {
+ return SDODataTypes.CHARACTER_STR;
+ } else if (sdoType == SDODataTypes.DATE) {
+ return SDODataTypes.DATE_STR;
+ } else if (sdoType == SDODataTypes.DATETIME) {
+ return SDODataTypes.DATETIME_STR;
+ } else if (sdoType == SDODataTypes.DAY) {
+ return SDODataTypes.DAY_STR;
+ } else if (sdoType == SDODataTypes.DECIMAL) {
+ return SDODataTypes.DECIMAL_STR;
+ } else if (sdoType == SDODataTypes.DOUBLE) {
+ return SDODataTypes.DOUBLE_STR;
+ } else if (sdoType == SDODataTypes.DURATION) {
+ return SDODataTypes.DURATION_STR;
+ } else if (sdoType == SDODataTypes.FLOAT) {
+ return SDODataTypes.FLOAT_STR;
+ } else if (sdoType == SDODataTypes.INT) {
+ return SDODataTypes.INT_STR;
+ } else if (sdoType == SDODataTypes.INTEGER) {
+ return SDODataTypes.INTEGER_STR;
+ } else if (sdoType == SDODataTypes.LONG) {
+ return SDODataTypes.LONG_STR;
+ } else if (sdoType == SDODataTypes.MONTH) {
+ return SDODataTypes.MONTH_STR;
+ } else if (sdoType == SDODataTypes.MONTHDAY) {
+ return SDODataTypes.MONTHDAY_STR;
+ } else if (sdoType == SDODataTypes.OBJECT) {
+ return SDODataTypes.OBJECT_STR;
+ } else if (sdoType == SDODataTypes.SHORT) {
+ return SDODataTypes.SHORT_STR;
+ } else if (sdoType == SDODataTypes.STRING) {
+ return SDODataTypes.STRING_STR;
+ } else if (sdoType == SDODataTypes.STRINGS) {
+ return SDODataTypes.STRINGS_STR;
+ } else if (sdoType == SDODataTypes.TIME) {
+ return SDODataTypes.TIME_STR;
+ } else if (sdoType == SDODataTypes.URI) {
+ return SDODataTypes.URI_STR;
+ } else if (sdoType == SDODataTypes.YEAR) {
+ return SDODataTypes.YEAR_STR;
+ } else if (sdoType == SDODataTypes.YEARMONTH) {
+ return SDODataTypes.YEARMONTH_STR;
+ } else if (sdoType == SDODataTypes.YEARMONTHDAY) {
+ return SDODataTypes.YEARMONTHDAY_STR;
+ } else if (sdoType == SDODataTypes.BOOLEANOBJECT) {
+ return SDODataTypes.BOOLEANOBJECT_STR;
+ } else if (sdoType == SDODataTypes.BYTEOBJECT) {
+ return SDODataTypes.BYTEOBJECT_STR;
+ } else if (sdoType == SDODataTypes.CHARACTEROBJECT) {
+ return SDODataTypes.CHARACTEROBJECT_STR;
+ } else if (sdoType == SDODataTypes.DOUBLEOBJECT) {
+ return SDODataTypes.DOUBLEOBJECT_STR;
+ } else if (sdoType == SDODataTypes.FLOATOBJECT) {
+ return SDODataTypes.FLOATOBJECT_STR;
+ } else if (sdoType == SDODataTypes.INTEGEROBJECT) {
+ return SDODataTypes.INTEGEROBJECT_STR;
+ } else if (sdoType == SDODataTypes.LONGOBJECT) {
+ return SDODataTypes.LONGOBJECT_STR;
+ } else if (sdoType == SDODataTypes.SHORTOBJECT) {
+ return SDODataTypes.SHORTOBJECT_STR;
+ } else {
+ throw new RuntimeException("Not a valid SDO Type " + sdoType);
+ }
+ }
+
+ public static int sqlTypeFor(Type sdoType) {
+ if (sdoType == null) {
+ return Types.OTHER;
+ }
+
+ if (sdoType == SDODataTypes.BOOLEAN) {
+ return Types.BOOLEAN;
+ } else if (sdoType == SDODataTypes.STRING) {
+ return Types.VARCHAR;
+ } else if (sdoType == SDODataTypes.BYTE) {
+ return Types.TINYINT;
+ } else if (sdoType == SDODataTypes.BYTES) {
+ return Types.BINARY;
+ } else if (sdoType == SDODataTypes.CHARACTER) {
+ return Types.CHAR;
+ } else if (sdoType == SDODataTypes.DATE) {
+ return Types.DATE;
+ } else if (sdoType == SDODataTypes.DATETIME) {
+ return Types.DATE;
+ } else if (sdoType == SDODataTypes.DAY) {
+ return java.sql.Types.BINARY;
+ } else if (sdoType == SDODataTypes.DECIMAL) {
+ return java.sql.Types.DECIMAL;
+ } else if (sdoType == SDODataTypes.DOUBLE) {
+ return java.sql.Types.DOUBLE;
+ } else if (sdoType == SDODataTypes.DURATION) {
+ return java.sql.Types.VARCHAR;
+ } else if (sdoType == SDODataTypes.FLOAT) {
+ return java.sql.Types.REAL;
+ } else if (sdoType == SDODataTypes.INT) {
+ return java.sql.Types.INTEGER;
+ } else if (sdoType == SDODataTypes.INTEGER) {
+ return java.sql.Types.INTEGER;
+ } else if (sdoType == SDODataTypes.LONG) {
+ return java.sql.Types.BIGINT;
+ } else if (sdoType == SDODataTypes.MONTH) {
+ return java.sql.Types.VARCHAR;
+ } else if (sdoType == SDODataTypes.MONTHDAY) {
+ return java.sql.Types.VARCHAR;
+ } else if (sdoType == SDODataTypes.OBJECT) {
+ return java.sql.Types.JAVA_OBJECT;
+ } else if (sdoType == SDODataTypes.SHORT) {
+ return java.sql.Types.SMALLINT;
+ } else if (sdoType == SDODataTypes.STRING) {
+ return java.sql.Types.VARCHAR;
+ } else if (sdoType == SDODataTypes.STRINGS) {
+ return java.sql.Types.OTHER;
+ } else if (sdoType == SDODataTypes.TIME) {
+ return java.sql.Types.VARCHAR;
+ } else if (sdoType == SDODataTypes.URI) {
+ return java.sql.Types.VARCHAR;
+ } else if (sdoType == SDODataTypes.YEAR) {
+ return java.sql.Types.VARCHAR;
+ } else if (sdoType == SDODataTypes.YEARMONTH) {
+ return java.sql.Types.VARCHAR;
+ } else if (sdoType == SDODataTypes.YEARMONTHDAY) {
+ return java.sql.Types.VARCHAR;
+ } else if (sdoType == SDODataTypes.BOOLEANOBJECT) {
+ return java.sql.Types.BOOLEAN;
+ } else if (sdoType == SDODataTypes.BYTEOBJECT) {
+ return java.sql.Types.TINYINT;
+ } else if (sdoType == SDODataTypes.CHARACTEROBJECT) {
+ return java.sql.Types.CHAR;
+ } else if (sdoType == SDODataTypes.DOUBLEOBJECT) {
+ return java.sql.Types.DOUBLE;
+ } else if (sdoType == SDODataTypes.FLOATOBJECT) {
+ return java.sql.Types.REAL;
+ } else if (sdoType == SDODataTypes.INTEGEROBJECT) {
+ return java.sql.Types.INTEGER;
+ } else if (sdoType == SDODataTypes.LONGOBJECT) {
+ return java.sql.Types.BIGINT;
+ } else if (sdoType == SDODataTypes.SHORTOBJECT) {
+ return java.sql.Types.SMALLINT;
+ } else {
+ throw new RuntimeException("Not a valid SDO Type " + sdoType);
+ }
+
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java
new file mode 100644
index 0000000000..ad213e5994
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java
@@ -0,0 +1,131 @@
+/*
+ * 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 commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+
+/**
+ * Defines SDO data types. This is used primalirly to type stored procedure OUT parameters.
+ *
+ */
+public class SDODataTypes {
+
+ public static final TypeHelper TYPE_HELPER = TypeHelper.INSTANCE;
+
+ public static final Type BOOLEAN = TYPE_HELPER.getType("commonj.sdo", "Boolean");
+ public static final String BOOLEAN_STR = "commonj.sdo.Boolean";
+
+ public static final Type BYTE = TYPE_HELPER.getType("commonj.sdo", "Byte");
+ public static final String BYTE_STR = "commonj.sdo.Byte";
+
+ public static final Type BYTES = TYPE_HELPER.getType("commonj.sdo", "Bytes");
+ public static final String BYTES_STR = "commonj.sdo.Bytes";
+
+ public static final Type CHARACTER = TYPE_HELPER.getType("commonj.sdo", "Character");
+ public static final String CHARACTER_STR = "commonj.sdo.Character";
+
+ public static final Type DATE = TYPE_HELPER.getType("commonj.sdo", "Date");
+ public static final String DATE_STR = "commonj.sdo.Date";
+
+ public static final Type DATETIME = TYPE_HELPER.getType("commonj.sdo", "Date");
+ public static final String DATETIME_STR = "commonj.sdo.Date";
+
+ public static final Type DAY = TYPE_HELPER.getType("commonj.sdo", "Date");
+ public static final String DAY_STR = "commonj.sdo.Day";
+
+ public static final Type DECIMAL = TYPE_HELPER.getType("commonj.sdo", "Float");
+ public static final String DECIMAL_STR = "commonj.sdo.Float";
+
+ public static final Type DOUBLE = TYPE_HELPER.getType("commonj.sdo", "Double");
+ public static final String DOUBLE_STR = "commonj.sdo.Double";
+
+ public static final Type DURATION = TYPE_HELPER.getType("commonj.sdo", "Date");
+ public static final String DURATION_STR = "commonj.sdo.Date";
+
+ public static final Type FLOAT = TYPE_HELPER.getType("commonj.sdo", "Float");
+ public static final String FLOAT_STR = "commonj.sdo.Float";
+
+ public static final Type INT = TYPE_HELPER.getType("commonj.sdo", "Int");
+ public static final String INT_STR = "commonj.sdo.Int";
+
+ public static final Type INTEGER = TYPE_HELPER.getType("commonj.sdo", "Integer");
+ public static final String INTEGER_STR = "commonj.sdo.Integer";
+
+ public static final Type LONG = TYPE_HELPER.getType("commonj.sdo", "Long");
+ public static final String LONG_STR = "commonj.sdo.Long";
+
+ public static final Type MONTH = TYPE_HELPER.getType("commonj.sdo", "Date");
+ public static final String MONTH_STR = "commonj.sdo.Date";
+
+ public static final Type MONTHDAY = TYPE_HELPER.getType("commonj.sdo", "Date");
+ public static final String MONTHDAY_STR = "commonj.sdo.Date";
+
+ public static final Type OBJECT = TYPE_HELPER.getType("commonj.sdo", "Object");
+ public static final String OBJECT_STR = "commonj.sdo.Object";
+
+ public static final Type SHORT = TYPE_HELPER.getType("commonj.sdo", "Short");
+ public static final String SHORT_STR = "commonj.sdo.Short";
+
+ public static final Type STRING = TYPE_HELPER.getType("commonj.sdo", "String");
+ public static final String STRING_STR = "commonj.sdo.String";
+
+ public static final Type STRINGS = TYPE_HELPER.getType("commonj.sdo", "String");
+ public static final String STRINGS_STR = "commonj.sdo.String";
+
+ public static final Type TIME = TYPE_HELPER.getType("commonj.sdo", "Date");
+ public static final String TIME_STR = "commonj.sdo.Date";
+
+ public static final Type URI = TYPE_HELPER.getType("commonj.sdo", "String");
+ public static final String URI_STR = "commonj.sdo.String";
+
+ public static final Type YEAR = TYPE_HELPER.getType("commonj.sdo", "Date");
+ public static final String YEAR_STR = "commonj.sdo.Date";
+
+ public static final Type YEARMONTH = TYPE_HELPER.getType("commonj.sdo", "Date");
+ public static final String YEARMONTH_STR = "commonj.sdo.Date";
+
+ public static final Type YEARMONTHDAY = TYPE_HELPER.getType("commonj.sdo", "Date");
+ public static final String YEARMONTHDAY_STR = "commonj.sdo.Date";
+
+ public static final Type BOOLEANOBJECT = TYPE_HELPER.getType("commonj.sdo", "BooleanObject");
+ public static final String BOOLEANOBJECT_STR = "commonj.sdo.BooleanObject";
+
+ public static final Type BYTEOBJECT = TYPE_HELPER.getType("commonj.sdo", "ByteObject");
+ public static final String BYTEOBJECT_STR = "commonj.sdo.ByteObject";
+
+ public static final Type CHARACTEROBJECT = TYPE_HELPER.getType("commonj.sdo", "CharacterObject");
+ public static final String CHARACTEROBJECT_STR = "commonj.sdo.CharacterObject";
+
+ public static final Type DOUBLEOBJECT = TYPE_HELPER.getType("commonj.sdo", "DoubleObject");
+ public static final String DOUBLEOBJECT_STR = "commonj.sdo.DoubleObject";
+
+ public static final Type FLOATOBJECT = TYPE_HELPER.getType("commonj.sdo", "FloatObject");
+ public static final String FLOATOBJECT_STR = "commonj.sdo.FloatObject";
+
+ public static final Type INTEGEROBJECT = TYPE_HELPER.getType("commonj.sdo", "IntObject");
+ public static final String INTEGEROBJECT_STR = "commonj.sdo.IntObject";
+
+ public static final Type LONGOBJECT = TYPE_HELPER.getType("commonj.sdo", "LongObject");
+ public static final String LONGOBJECT_STR = "commonj.sdo.LongObject";
+
+ public static final Type SHORTOBJECT = TYPE_HELPER.getType("commonj.sdo", "ShortObject");
+ public static final String SHORTOBJECT_STR = "commonj.sdo.ShortObject";
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java
new file mode 100644
index 0000000000..c1822c3e07
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java
@@ -0,0 +1,100 @@
+/*
+ * 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.sql.SQLException;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.config.Parameter;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+
+public class SPCommandImpl extends ReadCommandImpl {
+ private final Logger logger = Logger.getLogger(SPCommandImpl.class);
+
+ public SPCommandImpl(String sqlString, MappingWrapper config, List params) {
+ super(sqlString, config, null);
+ Iterator i = params.iterator();
+ while (i.hasNext()) {
+ Parameter p = (Parameter) i.next();
+
+ int index = p.getColumnType().lastIndexOf('.');
+ String pkg = p.getColumnType().substring(0, index);
+ String typeName = p.getColumnType().substring(index + 1);
+
+ Type sdoType = TypeHelper.INSTANCE.getType(pkg, typeName);
+
+ String direction = ParameterExtendedImpl.IN;
+ if (ParameterExtendedImpl.OUT.equalsIgnoreCase(p.getDirection())) {
+ direction = ParameterExtendedImpl.OUT;
+ } else if (ParameterExtendedImpl.IN_OUT.equalsIgnoreCase(p.getDirection())) {
+ direction = ParameterExtendedImpl.IN_OUT;
+ }
+ parameters.findOrCreateParameterWithIndex(p.getIndex(), direction, sdoType);
+ }
+
+ }
+
+ public DataObject executeQuery() {
+
+ boolean success = false;
+ try {
+ List results = statement.executeCall(parameters);
+ success = true;
+
+ return buildGraph(results);
+ } catch (SQLException e) {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug(e);
+ }
+
+ throw new RuntimeException(e);
+ } finally {
+ if (success) {
+ statement.getConnection().cleanUp();
+ } else {
+ statement.getConnection().errorCleanUp();
+ }
+ }
+ }
+
+ public void execute() {
+
+ boolean success = false;
+ try {
+ statement.executeUpdateCall(parameters);
+ success = true;
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (success) {
+ statement.getConnection().cleanUp();
+ } else {
+ statement.getConnection().errorCleanUp();
+ }
+ }
+
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java
new file mode 100644
index 0000000000..bae802a2bc
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java
@@ -0,0 +1,233 @@
+/*
+ * 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.sql.CallableStatement;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+// TODO - Can use some refactoring. Much code is duplicated in "execute" methods
+public class Statement {
+
+ protected final String queryString;
+
+ protected ConnectionImpl jdbcConnection;
+
+ private final Logger logger = Logger.getLogger(Statement.class);
+
+ private PreparedStatement preparedStatement;
+
+ private boolean isPaging;
+
+ public Statement(String sqlString) {
+ this.queryString = sqlString;
+ }
+
+ public List executeQuery(ParametersExtendedImpl parameters) throws SQLException {
+
+ PreparedStatement ps = getPreparedStatement(new String[0]);
+ ps = setParameters(ps, parameters);
+ ResultSet rs = ps.executeQuery();
+
+ return Collections.singletonList(rs);
+ }
+
+ public List executeCall(ParametersExtendedImpl parameters) throws SQLException {
+
+ CallableStatement cs = jdbcConnection.prepareCall(queryString);
+
+ Iterator inParams = parameters.getInParameters().iterator();
+ while (inParams.hasNext()) {
+ ParameterExtendedImpl param = (ParameterExtendedImpl) inParams.next();
+ cs.setObject(param.getIndex(), param.getValue());
+ }
+
+ // register out parameters
+ Iterator outParams = parameters.getOutParameters().iterator();
+ while (outParams.hasNext()) {
+ ParameterExtendedImpl param = (ParameterExtendedImpl) outParams.next();
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Registering parameter " + param.getName());
+ }
+
+ cs.registerOutParameter(param.getIndex(), SDODataTypeHelper.sqlTypeFor(param.getType()));
+ }
+
+ // Using execute because Derby does not currenlty support
+ // executeQuery
+ // for SP
+ cs.execute();
+ List results = new ArrayList();
+ results.add(cs.getResultSet());
+ while (cs.getMoreResults(java.sql.Statement.KEEP_CURRENT_RESULT)) {
+ results.add(cs.getResultSet());
+ }
+
+ Iterator i = parameters.getOutParameters().iterator();
+ while (i.hasNext()) {
+ ParameterExtendedImpl param = (ParameterExtendedImpl) i.next();
+ param.setValue(cs.getObject(param.getIndex()));
+ }
+
+ return results;
+
+ }
+
+ public void executeUpdateCall(ParametersExtendedImpl parameters) throws SQLException {
+ CallableStatement cs = jdbcConnection.prepareCall(queryString);
+
+ Iterator inParams = parameters.getInParameters().iterator();
+ while (inParams.hasNext()) {
+ ParameterExtendedImpl param = (ParameterExtendedImpl) inParams.next();
+ cs.setObject(param.getIndex(), param.getValue());
+ }
+
+ // register out parameters
+ Iterator outParams = parameters.getOutParameters().iterator();
+ while (outParams.hasNext()) {
+ ParameterExtendedImpl param = (ParameterExtendedImpl) outParams.next();
+
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Registering parameter " + param.getName());
+ }
+
+ cs.registerOutParameter(param.getIndex(), SDODataTypeHelper.sqlTypeFor(param.getType()));
+ }
+
+ cs.execute();
+
+ Iterator out = parameters.getOutParameters().iterator();
+ while (out.hasNext()) {
+ ParameterExtendedImpl param = (ParameterExtendedImpl) out.next();
+ param.setValue(cs.getObject(param.getIndex()));
+ }
+
+ }
+
+ public int executeUpdate(ParametersExtendedImpl parameters, String[] generatedKeys) throws SQLException {
+ return executeUpdate(getPreparedStatement(generatedKeys), parameters);
+ }
+
+ public int executeUpdate(ParametersExtendedImpl parameters) throws SQLException {
+ return executeUpdate(parameters, new String[0]);
+ }
+
+ /**
+ * TODO - We need to look at using specific ps.setXXX methods when a type
+ * has been specified and try setObject otherwise.
+ */
+ private int executeUpdate(PreparedStatement ps, ParametersExtendedImpl parameters) throws SQLException {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Executing statement " + queryString);
+ }
+
+ Iterator i = parameters.getInParameters().iterator();
+ while (i.hasNext()) {
+ ParameterExtendedImpl param = (ParameterExtendedImpl) i.next();
+
+ Object value = param.getValue();
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Setting parameter " + param.getIndex() + " to " + value);
+ }
+
+ if (value == null) {
+ if (param.getType() == null) {
+ try {
+ ParameterMetaData pmd = ps.getParameterMetaData();
+ ps.setNull(param.getIndex(), pmd.getParameterType(param.getIndex()));
+ } catch (SQLException ex) {
+ ps.setNull(param.getIndex(), SDODataTypeHelper.sqlTypeFor(null));
+ }
+ } else {
+ ps.setNull(param.getIndex(), SDODataTypeHelper.sqlTypeFor(param.getType()));
+ }
+ } else {
+ ps.setObject(param.getIndex(), value);
+ }
+ }
+ return ps.executeUpdate();
+ }
+
+ protected PreparedStatement setParameters(PreparedStatement ps, ParametersExtendedImpl parameters) throws SQLException {
+ Iterator i = parameters.getInParameters().iterator();
+ while (i.hasNext()) {
+ ParameterExtendedImpl param = (ParameterExtendedImpl) i.next();
+ ps.setObject(param.getIndex(), param.getValue());
+ }
+ return ps;
+ }
+
+ public void setConnection(ConnectionImpl jdbcConnection) {
+ this.jdbcConnection = jdbcConnection;
+ }
+
+ public ConnectionImpl getConnection() {
+ return this.jdbcConnection;
+ }
+
+ private PreparedStatement getPreparedStatement(String[] returnKeys) throws SQLException {
+
+ if (preparedStatement == null) {
+ if (isPaging) {
+ preparedStatement = jdbcConnection.preparePagedStatement(queryString);
+ } else {
+ preparedStatement = jdbcConnection.prepareStatement(queryString, returnKeys);
+ }
+ }
+
+ return preparedStatement;
+ }
+
+ public Integer getGeneratedKey() throws SQLException {
+
+ if (getConnection().isGeneratedKeysSupported()) {
+ ResultSet rs = preparedStatement.getGeneratedKeys();
+ if (rs.next()) {
+ return new Integer(rs.getInt(1));
+ }
+ }
+
+ return null;
+ }
+
+ protected void enablePaging() {
+ isPaging = true;
+ }
+
+ public void close() {
+
+ if (this.preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java
new file mode 100644
index 0000000000..4155360341
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java
@@ -0,0 +1,37 @@
+/*
+ * 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 org.apache.tuscany.das.rdb.config.Update;
+
+public class UpdateCommandImpl extends WriteCommandImpl {
+ public UpdateCommandImpl(org.apache.tuscany.das.rdb.config.Command command) {
+ super(command);
+ }
+
+ public UpdateCommandImpl(String sqlString) {
+ super(sqlString);
+ }
+
+ public UpdateCommandImpl(Update update) {
+ super(update.getSql());
+ this.addParameters(update.getParameters());
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java
new file mode 100644
index 0000000000..e7bb58698c
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java
@@ -0,0 +1,45 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Updates don't have to be sorted, so this class is a simple wrapper of ArrayList.
+ *
+ */
+public class UpdateList {
+
+ private List updates = new ArrayList();
+
+ public UpdateList() {
+ super();
+ }
+
+ public void add(ChangeOperation c) {
+ updates.add(c);
+ }
+
+ public Collection getSortedList() {
+ return updates;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java
new file mode 100644
index 0000000000..1bcf3441b6
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java
@@ -0,0 +1,32 @@
+/*
+ * 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 commonj.sdo.DataObject;
+
+
+public class UpdateOperation extends ChangeOperation {
+
+ public UpdateOperation(UpdateCommandImpl command, DataObject changedObject, String id) {
+ super(command, changedObject);
+ this.propagatedID = id;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java
new file mode 100644
index 0000000000..5ce2ed6992
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java
@@ -0,0 +1,165 @@
+/*
+ * 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.SQLException;
+import java.util.List;
+import java.util.TreeMap;
+
+import org.apache.tuscany.das.rdb.config.Config;
+import org.apache.tuscany.das.rdb.config.ResultDescriptor;
+import org.apache.tuscany.das.rdb.config.impl.ParameterImpl;
+import org.apache.tuscany.das.rdb.config.Parameters;
+
+import commonj.sdo.DataObject;
+
+public abstract class WriteCommandImpl extends CommandImpl {
+
+ public WriteCommandImpl(org.apache.tuscany.das.rdb.config.Command command) {
+ super(command);
+ }
+
+ public WriteCommandImpl(String sqlString) {
+ super(sqlString);
+ }
+
+ public void setResultDescriptors(List resultDescriptorList){
+ //ignore , applicable for ReadCommand only
+ }
+
+ public List getResultDescriptors(){
+ //ignore, applicable for ReadCommand only
+ return null;
+ }
+
+ public void addResultDescriptor(ResultDescriptor resultDescriptor){
+ //ignore
+ }
+
+
+ public ResultDescriptor removeResultDescriptor(int index){
+ return null;
+ }
+
+ public ResultDescriptor removeResultDescriptor(ResultDescriptor resultDescriptor){
+ return null;
+ }
+
+ public ResultDescriptor getResultDescriptor(int index){
+ return null;
+ }
+
+ public void printResultDescriptors(OutputStream ostrm) throws IOException{
+ //ignore
+ }
+
+ public void execute() {
+
+ boolean success = false;
+ try {
+ basicExecute();
+ success = true;
+ } finally {
+ if (success) {
+ statement.getConnection().cleanUp();
+ } else {
+ statement.getConnection().errorCleanUp();
+ }
+ }
+
+ }
+
+ public void basicExecute() {
+ try {
+ statement.executeUpdate(parameters);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public DataObject executeQuery() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Config getMappingModel() {
+ return configWrapper.getConfig();
+ }
+
+ public String toString() {
+
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("\nSQL: " + statement.queryString);
+
+ return buffer.toString();
+ }
+
+ public int getGeneratedKey() {
+ throw new RuntimeException("No generated key is available");
+ }
+
+ //it is acceptable if params having index set by caller are listed in any order in Parameters
+ //but, if index is not set by caller, the order of parameters in Parameters should be in sync
+ //with the Command string parameters
+ protected void addParameters(Parameters parameters) {
+ List params = parameters.getParameter();
+ if(params == null)
+ return;
+
+ boolean paramsIndexed = true;
+ TreeMap sortedParams = null;
+ for(int i=0; i<params.size(); i++){
+ if(((ParameterImpl)params.get(i)).getIndex() <= 0){
+ paramsIndexed=false; //any index not set, ignore all externally set indexes and do auto indexing
+ break;
+ }
+ }
+
+ //auto-indexing
+ if(!paramsIndexed) {
+ for(int i=0; i<params.size(); i++){
+ ParameterExtendedImpl param = new ParameterExtendedImpl((ParameterImpl)params.get(i));
+ param.setIndex(i+1);
+ this.addParameter(param);
+ }
+ return;
+ }
+ else {//dont allow duplicates and check indexing with +1 increment from 1st to last param
+ sortedParams = new TreeMap();
+ for(int i=0; i<params.size(); i++){
+ ParameterImpl existingParam = (ParameterImpl)sortedParams.put( new Integer(((ParameterImpl)params.get(i)).getIndex()), ((ParameterImpl)params.get(i)));
+ if(existingParam != null) {
+ throw new RuntimeException("Parameters with duplicate indexes!");
+ }
+ }
+
+ if( ((Integer)sortedParams.firstKey()).intValue() + sortedParams.size() -1 !=
+ ((Integer)sortedParams.lastKey()).intValue()) {
+ throw new RuntimeException("Parameters with improper indexes!");
+ }
+ }
+
+ for(int i=0; i<params.size(); i++) {
+ ParameterExtendedImpl param = new ParameterExtendedImpl((ParameterImpl)params.get(i));
+ param.setIndex(((ParameterImpl)params.get(i)).getIndex());
+ this.addParameter(param);
+ }
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java
new file mode 100644
index 0000000000..9395b6c1b1
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java
@@ -0,0 +1,228 @@
+/*
+ * 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.merge.impl;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.log4j.Logger;
+
+import org.apache.tuscany.das.rdb.config.Config;
+import org.apache.tuscany.das.rdb.config.wrapper.QualifiedColumn;
+import org.apache.tuscany.das.rdb.graphbuilder.impl.MultiTableRegistry;
+import org.apache.tuscany.das.rdb.graphbuilder.impl.TableRegistry;
+import org.apache.tuscany.sdo.impl.ChangeSummaryImpl;
+import org.apache.tuscany.sdo.api.SDOUtil;
+
+import commonj.sdo.ChangeSummary;
+import commonj.sdo.DataGraph;
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+import commonj.sdo.impl.HelperProvider;
+
+public class GraphMerger {
+
+ private static Logger logger = Logger.getLogger("GraphMerger");
+
+ private Map keys = new HashMap();
+
+ private TableRegistry registry = new MultiTableRegistry();
+
+ private Config config = null;//JIRA-962 for any new tests with schema , we need this
+
+ // TODO lots of cleanup/design
+ public GraphMerger() {
+ // Empty Constructor
+ }
+
+ //JIRA-952
+ public GraphMerger(Config cfg) {
+ this.config = cfg;
+ }
+
+ // TODO Replace EMF reference with SDOUtil function when available
+ // (Tuscany-583)
+ public DataObject emptyGraph(Config config) {
+
+ if (config.getDataObjectModel() == null) {
+ throw new RuntimeException("DataObjectModel must be specified in the Config");
+ }
+
+ String uri = "http:///org.apache.tuscany.das.rdb/das";
+ TypeHelper typeHelper = HelperProvider.getDefaultContext().getTypeHelper();
+ Type rootType = null;
+ rootType = typeHelper.getType(uri + "/DataGraphRoot", "DataGraphRoot");
+ if(rootType == null){
+ rootType = SDOUtil.createType(HelperProvider.getDefaultContext(), uri + "/DataGraphRoot", "DataGraphRoot", false);
+ if (logger.isDebugEnabled()) {
+ logger.debug("GraphMerger.emptyGraph():creating type for "+uri);
+ }
+ }
+
+ List types = SDOUtil.getTypes(HelperProvider.getDefaultContext(), config.getDataObjectModel());
+ if (types == null) {
+ throw new RuntimeException("SDO Types have not been registered for URI " + config.getDataObjectModel());
+ }
+
+ Iterator i = types.iterator();
+ while (i.hasNext()) {
+ Type type = (Type) i.next();
+ Property property = rootType.getProperty(type.getName());
+ if( !(property != null &&
+ (property.getType().isDataType()== type.isDataType()) &&
+ (property.isContainment() == true) &&
+ (property.isMany() == true)) ){
+ property = SDOUtil.createProperty(rootType, type.getName(), type);
+ SDOUtil.setContainment(property, true);
+ SDOUtil.setMany(property, true);
+ }
+ }
+
+ // Create the DataGraph
+ DataGraph g = SDOUtil.createDataGraph();
+
+ // Create the root object
+ g.createRootObject(rootType);
+
+ ChangeSummary summary = g.getChangeSummary();
+ summary.beginLogging();
+
+ return g.getRootObject();
+ }
+
+ public DataObject merge(List graphs) {
+ DataObject primaryGraph = (DataObject) graphs.get(0);
+
+ Iterator i = graphs.iterator();
+ if (i.hasNext()) {
+ i.next();
+ }
+ while (i.hasNext()) {
+ primaryGraph = merge(primaryGraph, (DataObject) i.next());
+ }
+
+ return primaryGraph;
+ }
+
+ public DataObject merge(DataObject primary, DataObject secondary) {
+ addGraphToRegistry(primary);
+
+ ChangeSummary summary = primary.getDataGraph().getChangeSummary();
+ summary.endLogging();
+ Iterator i = secondary.getType().getProperties().iterator();
+
+ while (i.hasNext()) {
+ Property p = (Property) i.next();
+
+ Iterator objects = secondary.getList(p.getName()).iterator();
+ while (objects.hasNext()) {
+ DataObject object = (DataObject) objects.next();
+ createObjectWithSubtree(primary, p, object);
+ }
+ }
+ ((ChangeSummaryImpl) summary).resumeLogging();
+ return primary;
+ }
+
+ private void createObjectWithSubtree(DataObject root, Property p, DataObject object) {
+ Object pk = getPrimaryKey(object);
+
+ if (!registry.contains(object.getType().getName(), Collections.singletonList(pk))) {
+ DataObject newObject = root.createDataObject(p.getName());
+ Iterator attrs = object.getType().getProperties().iterator();
+ while (attrs.hasNext()) {
+ Property attr = (Property) attrs.next();
+ if (attr.getType().isDataType()) {
+ newObject.set(attr.getName(), object.get(attr));
+ }
+ }
+ registry.put(object.getType().getName(), Collections.singletonList(pk), newObject);
+ Iterator refs = object.getType().getProperties().iterator();
+ while (refs.hasNext()) {
+ Property ref = (Property) refs.next();
+ if (!ref.getType().isDataType()) {
+ List refObjects;
+ if (!ref.isMany()) {
+ refObjects = Collections.singletonList(object.get(ref));
+ } else {
+ refObjects = (List) object.get(ref);
+ }
+ Iterator iter = refObjects.iterator();
+ while (iter.hasNext()) {
+ DataObject refObject = (DataObject) iter.next();
+ createObjectWithSubtree(root, refObject.getContainmentProperty(), refObject);
+ refObject = registry.get(refObject.getType().getName(),
+ Collections.singletonList(getPrimaryKey(refObject)));
+ if (ref.isMany()) {
+ newObject.getList(newObject.getType().getProperty(ref.getName())).add(refObject);
+ } else {
+ newObject.set(newObject.getType().getProperty(ref.getName()), refObject);
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ private void addGraphToRegistry(DataObject graph1) {
+ Iterator i = graph1.getType().getProperties().iterator();
+ while (i.hasNext()) {
+ Property p = (Property) i.next();
+ Iterator objects = graph1.getList(p).iterator();
+ while (objects.hasNext()) {
+ DataObject object = (DataObject) objects.next();
+ Object pk = object.get(getPrimaryKeyName(object));
+ if (logger.isDebugEnabled()) {
+ logger.debug("Adding object with pk " + pk + " to registry");
+ }
+ registry.put(object.getType().getName(), Collections.singletonList(pk), object);
+ }
+ }
+ }
+
+ private Object getPrimaryKey(DataObject object) {
+ String pkName = getPrimaryKeyName(object);
+ return object.get(pkName);
+ }
+
+ private String getPrimaryKeyName(DataObject object) {
+ return (String) keys.get(object.getType().getName());
+ }
+
+ //JIRA-952
+ public void addPrimaryKey(String key) {
+ QualifiedColumn column = null;
+ if(this.config != null && this.config.isDatabaseSchemaNameSupported()){
+ column = new QualifiedColumn(key, this.config.isDatabaseSchemaNameSupported());
+ }
+ else{
+ column = new QualifiedColumn(key);
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Adding " + column.getTableName() + " " + column.getColumnName() + " to keys");
+ }
+ keys.put(column.getTableName(), column.getColumnName());
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/CollectionsUtil.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/CollectionsUtil.java
new file mode 100644
index 0000000000..64e8826f76
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/CollectionsUtil.java
@@ -0,0 +1,49 @@
+/*
+ * 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.util;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ */
+public final class CollectionsUtil {
+
+ private CollectionsUtil() {
+
+ }
+
+ // Utilities
+ public static boolean disjoint(Collection c1, Collection c2) {
+
+ if (c1.size() > c2.size()) {
+ Collection c = c1;
+ c1 = c2;
+ c2 = c;
+ }
+ for (Iterator iterator = c2.iterator(); iterator.hasNext();) {
+ Object o = (Object)iterator.next();
+ if (c1.contains(o)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/ConfigUtil.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/ConfigUtil.java
new file mode 100644
index 0000000000..c5c7a38aab
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/ConfigUtil.java
@@ -0,0 +1,130 @@
+/*
+ * 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.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tuscany.das.rdb.config.Command;
+import org.apache.tuscany.das.rdb.config.Config;
+import org.apache.tuscany.das.rdb.config.ConfigFactory;
+import org.apache.tuscany.das.rdb.config.Create;
+import org.apache.tuscany.das.rdb.config.Delete;
+import org.apache.tuscany.das.rdb.config.Parameter;
+import org.apache.tuscany.das.rdb.config.Update;
+
+import commonj.sdo.helper.HelperContext;
+import commonj.sdo.helper.XMLHelper;
+import commonj.sdo.impl.HelperProvider;
+
+/**
+ * Config util provides config-related utilities such as loading a Config
+ * instance from an InputStream
+ *
+ */
+public final class ConfigUtil {
+
+ private ConfigUtil() {
+
+ }
+
+ public static Config loadConfig(InputStream configStream) {
+
+ if (configStream == null) {
+ throw new RuntimeException("Cannot load configuration from a null InputStream. "
+ + "Possibly caused by an incorrect config xml file name");
+ }
+
+ HelperContext context = HelperProvider.getDefaultContext();
+ ConfigFactory.INSTANCE.register(context);
+ XMLHelper helper = context.getXMLHelper();
+
+ try {
+ return (Config) helper.load(configStream).getRootObject();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static String getParameters(Create createCommand) {
+ List parameters = createCommand.getParameters().getParameter();
+ if(parameters != null) {
+ Iterator itr = parameters.iterator();
+ StringBuffer serializedParameters = new StringBuffer();
+
+ while(itr.hasNext()) {
+ serializedParameters.append(((Parameter)itr.next()).getName()+" ");
+ }
+ return serializedParameters.toString().trim();
+ }
+ else {
+ return null;
+ }
+ }
+
+ public static String getParameters(Update updateCommand) {
+ List parameters = updateCommand.getParameters().getParameter();
+ if(parameters != null) {
+ Iterator itr = parameters.iterator();
+ StringBuffer serializedParameters = new StringBuffer();
+
+ while(itr.hasNext()) {
+ serializedParameters.append(((Parameter)itr.next()).getName()+" ");
+ }
+ return serializedParameters.toString().trim();
+ }
+ else {
+ return null;
+ }
+ }
+
+ public static String getParameters(Delete deleteCommand) {
+ List parameters = deleteCommand.getParameters().getParameter();
+ if(parameters != null) {
+ Iterator itr = parameters.iterator();
+ StringBuffer serializedParameters = new StringBuffer();
+
+ while(itr.hasNext()) {
+ serializedParameters.append(((Parameter)itr.next()).getName()+" ");
+ }
+ return serializedParameters.toString().trim();
+ }
+ else {
+ return null;
+ }
+ }
+
+ public static String getParameters(Command command) {
+ List parameters = command.getParameter();
+ if(parameters != null) {
+ Iterator itr = parameters.iterator();
+ StringBuffer serializedParameters = new StringBuffer();
+
+ while(itr.hasNext()) {
+ serializedParameters.append(((Parameter)itr.next()).getName()+" ");
+ }
+ return serializedParameters.toString().trim();
+ }
+ else {
+ return null;
+ }
+ }
+}
diff --git a/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DataObjectUtil.java b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DataObjectUtil.java
new file mode 100644
index 0000000000..b9649669e5
--- /dev/null
+++ b/das-java/tags/1.0-incubating-beta2/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DataObjectUtil.java
@@ -0,0 +1,79 @@
+/*
+ * 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.util;
+
+import java.util.Iterator;
+import java.util.List;
+
+import commonj.sdo.ChangeSummary;
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.ChangeSummary.Setting;
+import commonj.sdo.helper.DataFactory;
+
+/**
+ */
+public final class DataObjectUtil {
+
+ private DataObjectUtil() {
+
+ }
+
+ // Utilities
+ public static DataObject getRestoredCopy(DataObject changedDO) {
+ DataObject changedCopy = getCopy(changedDO);
+ restoreAttributeValues(changedCopy, changedDO);
+ return changedCopy;
+ }
+
+ public static DataObject getCopy(DataObject original) {
+
+ DataObject copy = DataFactory.INSTANCE.create(original.getType());
+
+ // Fill in values
+ Iterator i = original.getType().getProperties().iterator();
+ while (i.hasNext()) {
+ Property feature = (Property) i.next();
+ copy.set(feature, original.get(feature));
+ }
+ return copy;
+ }
+
+ /**
+ * @param changedCopy
+ * @return
+ */
+ private static void restoreAttributeValues(DataObject changedCopy, DataObject changedDO) {
+
+ ChangeSummary changeSummary = changedDO.getDataGraph().getChangeSummary();
+ List changes = changeSummary.getOldValues(changedDO);
+ if (changes == null) {
+ return;
+ }
+
+ Iterator i = changes.iterator();
+ while (i.hasNext()) {
+ Setting s = (Setting) i.next();
+ if (s.getProperty().getType().isDataType()) {
+ changedCopy.set(s.getProperty(), s.getValue());
+ }
+ }
+ }
+
+}