summaryrefslogtreecommitdiffstats
path: root/das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl
diff options
context:
space:
mode:
Diffstat (limited to 'das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl')
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java79
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java62
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java177
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java87
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java241
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java82
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CollisionParameter.java31
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java178
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java154
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java30
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java50
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java313
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java202
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java37
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java77
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java38
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java57
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java75
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java95
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java39
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java48
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java69
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterExtendedImpl.java98
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java120
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java113
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParametersExtendedImpl.java189
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java338
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java161
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java187
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java131
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java100
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java233
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java37
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java45
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java32
-rw-r--r--das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java165
36 files changed, 4170 insertions, 0 deletions
diff --git a/das-java/tags/1.0-incubating-beta2-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CollisionParameter.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterExtendedImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParametersExtendedImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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-rc1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java b/das-java/tags/1.0-incubating-beta2-rc1/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-rc1/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);
+ }
+ }
+}