summaryrefslogtreecommitdiffstats
path: root/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl
diff options
context:
space:
mode:
Diffstat (limited to 'das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl')
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java79
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java50
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java177
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java87
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java241
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java82
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CollisionParameter.java31
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java99
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java125
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java30
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java50
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java313
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java202
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java34
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java77
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java38
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java57
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java66
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java95
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java39
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java48
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java69
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java120
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java113
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java124
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java161
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java109
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java98
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java100
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java233
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java34
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java45
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java32
-rw-r--r--das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java88
34 files changed, 3346 insertions, 0 deletions
diff --git a/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java
new file mode 100644
index 0000000000..b19aab85e8
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java
new file mode 100644
index 0000000000..d1b990d421
--- /dev/null
+++ b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.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.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();
+
+ public void setConnection(Connection connection) {
+ setConnection(new ConnectionImpl(connection));
+ }
+
+ public void setConnection(Connection connection, Config config) {
+ boolean managed = true;
+ if (config != null && config.getConnectionInfo() != null) {
+ managed = config.getConnectionInfo().isManagedtx();
+ }
+ setConnection(connection, managed);
+ }
+
+ public void setConnection(Connection connection, boolean manageTransaction) {
+ ConnectionImpl c = new ConnectionImpl(connection);
+ c.setManageTransactions(manageTransaction);
+ setConnection(c);
+ }
+
+ public abstract void setConnection(ConnectionImpl c);
+
+}
diff --git a/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java
new file mode 100644
index 0000000000..c348eae54e
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java
new file mode 100644
index 0000000000..81562dcbd7
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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()) {
+ ParameterImpl parm = (ParameterImpl) 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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java
new file mode 100644
index 0000000000..52300e6c9b
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.apache.tuscany.das.rdb.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.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()))
+ && (Collections.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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java
new file mode 100644
index 0000000000..2cc5f906c9
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CollisionParameter.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CollisionParameter.java
new file mode 100644
index 0000000000..a9cd9b1a40
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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 ParameterImpl {
+
+ private boolean isSet;
+
+ public void setValue(Object value) {
+ if (!isSet) {
+ this.value = value;
+ isSet = true;
+ }
+ }
+}
diff --git a/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java
new file mode 100644
index 0000000000..8c5658935f
--- /dev/null
+++ b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java
@@ -0,0 +1,99 @@
+/*
+ * 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.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 Parameters parameters = new Parameters();
+
+
+
+ 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 abstract void execute();
+
+ public abstract DataObject executeQuery();
+
+ public void setParameter(int index, Object value) {
+ parameters.setParameter(index, value);
+ }
+
+ public void addParameter(ParameterImpl param) {
+ parameters.add(param);
+ }
+
+ public List getParameters() {
+ return parameters.parameterList();
+ }
+
+ public Object getParameter(int index) {
+ return parameters.parameterWithIndex(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();
+ }
+
+}
diff --git a/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java
new file mode 100644
index 0000000000..76baa8ca0d
--- /dev/null
+++ b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java
@@ -0,0 +1,125 @@
+/*
+ * 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 final boolean useGetGeneratedKeys;
+
+ public ConnectionImpl(Connection connection) {
+ this.connection = connection;
+
+ try {
+ DatabaseMetaData dbmd = connection.getMetaData();
+
+ if (dbmd.getDatabaseProductName().contains("Oracle")) {
+ this.useGetGeneratedKeys = false;
+ } else {
+ this.useGetGeneratedKeys = true;
+ }
+ if (connection.getAutoCommit()) {
+ throw new RuntimeException("AutoCommit must be off");
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public Connection getJDBCConnection() {
+ return connection;
+ }
+
+ 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);
+ }
+
+ if (useGetGeneratedKeys) {
+ 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);
+ }
+
+ public boolean useGetGeneratedKeys() {
+ return this.useGetGeneratedKeys;
+ }
+}
diff --git a/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java
new file mode 100644
index 0000000000..0163f96686
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java
new file mode 100644
index 0000000000..ba80b3bcb5
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java
new file mode 100644
index 0000000000..863bb5754d
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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.getSQL(), configWrapper, commandConfig.getResultDescriptor()));
+ } else if (kind.equalsIgnoreCase("update")) {
+ commands.put(commandConfig.getName(), new UpdateCommandImpl(commandConfig.getSQL()));
+ } else if (kind.equalsIgnoreCase("insert")) {
+ commands.put(commandConfig.getName(), new InsertCommandImpl(commandConfig.getSQL(), new String[0]));
+ } else if (kind.equalsIgnoreCase("delete")) {
+ commands.put(commandConfig.getName(), new DeleteCommandImpl(commandConfig.getSQL()));
+ } 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, connection);
+ 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);
+ }
+
+} \ No newline at end of file
diff --git a/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java
new file mode 100644
index 0000000000..110fd1bd38
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java
new file mode 100644
index 0000000000..78e38cee0b
--- /dev/null
+++ b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java
@@ -0,0 +1,34 @@
+/*
+ * 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(String sqlString) {
+ super(sqlString);
+ }
+
+ public DeleteCommandImpl(Delete delete) {
+ super(delete.getSql());
+ addParameters(delete.getParameters());
+ }
+
+}
diff --git a/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java
new file mode 100644
index 0000000000..feb7e31411
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java
new file mode 100644
index 0000000000..52935599c1
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java
new file mode 100644
index 0000000000..bb148635c8
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java
new file mode 100644
index 0000000000..048ee7fef5
--- /dev/null
+++ b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java
@@ -0,0 +1,66 @@
+/*
+ * 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(String sqlString, String[] generatedKeys) {
+ super(sqlString);
+ keys = generatedKeys;
+ }
+
+ public InsertCommandImpl(Create create) {
+ super(create.getSql());
+ 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 {
+ return statement.getGeneratedKey();
+ } catch (SQLException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+}
diff --git a/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java
new file mode 100644
index 0000000000..e61ccfe21e
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java
new file mode 100644
index 0000000000..d91200fd03
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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 ParameterImpl {
+
+ public void setValue(Object oldValue) {
+ this.value = updateValue(oldValue);
+ }
+
+ private Object updateValue(Object oldValue) {
+ if (oldValue instanceof Integer) {
+ return Integer.valueOf(((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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java
new file mode 100644
index 0000000000..0a5f6951e9
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java
new file mode 100644
index 0000000000..27b653763b
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java
new file mode 100644
index 0000000000..3e23faf069
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java
new file mode 100644
index 0000000000..bebfba9ce9
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java
new file mode 100644
index 0000000000..defebc6f3e
--- /dev/null
+++ b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java
@@ -0,0 +1,124 @@
+/*
+ * 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.List;
+
+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.util.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;
+
+ 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
+ }
+ }
+
+
+ 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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java
new file mode 100644
index 0000000000..861b292bef
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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
+ public 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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java
new file mode 100644
index 0000000000..1038c9a99a
--- /dev/null
+++ b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java
@@ -0,0 +1,109 @@
+/*
+ * 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 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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java
new file mode 100644
index 0000000000..2052950272
--- /dev/null
+++ b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.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 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 Type BYTE = TYPE_HELPER.getType("commonj.sdo", "Byte");
+
+ public static final Type BYTES = TYPE_HELPER.getType("commonj.sdo", "Bytes");
+
+ public static final Type CHARACTER = TYPE_HELPER.getType("commonj.sdo", "Character");
+
+ public static final Type DATE = TYPE_HELPER.getType("commonj.sdo", "Date");
+
+ public static final Type DATETIME = TYPE_HELPER.getType("commonj.sdo", "Date");
+
+ public static final Type DAY = TYPE_HELPER.getType("commonj.sdo", "Date");
+
+ public static final Type DECIMAL = TYPE_HELPER.getType("commonj.sdo", "Float");
+
+ public static final Type DOUBLE = TYPE_HELPER.getType("commonj.sdo", "Double");
+
+ public static final Type DURATION = TYPE_HELPER.getType("commonj.sdo", "Date");
+
+ public static final Type FLOAT = TYPE_HELPER.getType("commonj.sdo", "Float");
+
+ public static final Type INT = TYPE_HELPER.getType("commonj.sdo", "Int");
+
+ public static final Type INTEGER = TYPE_HELPER.getType("commonj.sdo", "Integer");
+
+ public static final Type LONG = TYPE_HELPER.getType("commonj.sdo", "Long");
+
+ public static final Type MONTH = TYPE_HELPER.getType("commonj.sdo", "Date");
+
+ public static final Type MONTHDAY = TYPE_HELPER.getType("commonj.sdo", "Date");
+
+ public static final Type OBJECT = TYPE_HELPER.getType("commonj.sdo", "Object");
+
+ public static final Type SHORT = TYPE_HELPER.getType("commonj.sdo", "Short");
+
+ public static final Type STRING = TYPE_HELPER.getType("commonj.sdo", "String");
+
+ public static final Type STRINGS = TYPE_HELPER.getType("commonj.sdo", "String");
+
+ public static final Type TIME = TYPE_HELPER.getType("commonj.sdo", "Date");
+
+ public static final Type URI = TYPE_HELPER.getType("commonj.sdo", "String");
+
+ public static final Type YEAR = TYPE_HELPER.getType("commonj.sdo", "Date");
+
+ public static final Type YEARMONTH = TYPE_HELPER.getType("commonj.sdo", "Date");
+
+ public static final Type YEARMONTHDAY = TYPE_HELPER.getType("commonj.sdo", "Date");
+
+ public static final Type BOOLEANOBJECT = TYPE_HELPER.getType("commonj.sdo", "BooleanObject");
+
+ public static final Type BYTEOBJECT = TYPE_HELPER.getType("commonj.sdo", "ByteObject");
+
+ public static final Type CHARACTEROBJECT = TYPE_HELPER.getType("commonj.sdo", "CharacterObject");
+
+ public static final Type DOUBLEOBJECT = TYPE_HELPER.getType("commonj.sdo", "DoubleObject");
+
+ public static final Type FLOATOBJECT = TYPE_HELPER.getType("commonj.sdo", "FloatObject");
+
+ public static final Type INTEGEROBJECT = TYPE_HELPER.getType("commonj.sdo", "IntObject");
+
+ public static final Type LONGOBJECT = TYPE_HELPER.getType("commonj.sdo", "LongObject");
+
+ public static final Type SHORTOBJECT = TYPE_HELPER.getType("commonj.sdo", "ShortObject");
+
+}
diff --git a/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java
new file mode 100644
index 0000000000..e34069822d
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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);
+
+ int direction = ParameterImpl.IN;
+ if ("OUT".equalsIgnoreCase(p.getDirection())) {
+ direction = ParameterImpl.OUT;
+ } else if ("INOUT".equalsIgnoreCase(p.getDirection())) {
+ direction = ParameterImpl.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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java
new file mode 100644
index 0000000000..cc637e460a
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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(Parameters parameters) throws SQLException {
+
+ PreparedStatement ps = getPreparedStatement(new String[0]);
+ ps = setParameters(ps, parameters);
+ ResultSet rs = ps.executeQuery();
+
+ return Collections.singletonList(rs);
+ }
+
+ public List executeCall(Parameters parameters) throws SQLException {
+
+ CallableStatement cs = jdbcConnection.prepareCall(queryString);
+
+ Iterator inParams = parameters.inParams().iterator();
+ while (inParams.hasNext()) {
+ ParameterImpl param = (ParameterImpl) inParams.next();
+ cs.setObject(param.getIndex(), param.getValue());
+ }
+
+ // register out parameters
+ Iterator outParams = parameters.outParams().iterator();
+ while (outParams.hasNext()) {
+ ParameterImpl param = (ParameterImpl) 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.outParams().iterator();
+ while (i.hasNext()) {
+ ParameterImpl param = (ParameterImpl) i.next();
+ param.setValue(cs.getObject(param.getIndex()));
+ }
+
+ return results;
+
+ }
+
+ public void executeUpdateCall(Parameters parameters) throws SQLException {
+ CallableStatement cs = jdbcConnection.prepareCall(queryString);
+
+ Iterator inParams = parameters.inParams().iterator();
+ while (inParams.hasNext()) {
+ ParameterImpl param = (ParameterImpl) inParams.next();
+ cs.setObject(param.getIndex(), param.getValue());
+ }
+
+ // register out parameters
+ Iterator outParams = parameters.outParams().iterator();
+ while (outParams.hasNext()) {
+ ParameterImpl param = (ParameterImpl) 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.outParams().iterator();
+ while (out.hasNext()) {
+ ParameterImpl param = (ParameterImpl) out.next();
+ param.setValue(cs.getObject(param.getIndex()));
+ }
+
+ }
+
+ public int executeUpdate(Parameters parameters, String[] generatedKeys) throws SQLException {
+ return executeUpdate(getPreparedStatement(generatedKeys), parameters);
+ }
+
+ public int executeUpdate(Parameters 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, Parameters parameters) throws SQLException {
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Executing statement " + queryString);
+ }
+
+ Iterator i = parameters.inParams().iterator();
+ while (i.hasNext()) {
+ ParameterImpl param = (ParameterImpl) 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, Parameters parameters) throws SQLException {
+ Iterator i = parameters.inParams().iterator();
+ while (i.hasNext()) {
+ ParameterImpl param = (ParameterImpl) 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().useGetGeneratedKeys()) {
+ ResultSet rs = preparedStatement.getGeneratedKeys();
+ if (rs.next()) {
+ return Integer.valueOf(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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java
new file mode 100644
index 0000000000..11a78bb5d1
--- /dev/null
+++ b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java
@@ -0,0 +1,34 @@
+/*
+ * 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(String sqlString) {
+ super(sqlString);
+ }
+
+ public UpdateCommandImpl(Update update) {
+ super(update.getSql());
+ addParameters(update.getParameters());
+ }
+
+}
diff --git a/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java
new file mode 100644
index 0000000000..e7bb58698c
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java
new file mode 100644
index 0000000000..1bcf3441b6
--- /dev/null
+++ b/das-java/branches/das-java-beta1/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/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java
new file mode 100644
index 0000000000..ae082976eb
--- /dev/null
+++ b/das-java/branches/das-java-beta1/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java
@@ -0,0 +1,88 @@
+/*
+ * 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.StringTokenizer;
+
+import org.apache.tuscany.das.rdb.config.Config;
+
+import commonj.sdo.DataObject;
+
+public abstract class WriteCommandImpl extends CommandImpl {
+
+ public WriteCommandImpl(String sqlString) {
+ super(sqlString);
+ }
+
+ 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");
+ }
+
+ public void addParameters(String parameters) {
+ StringTokenizer tokenizer = new StringTokenizer(parameters);
+ for (int idx = 1; tokenizer.hasMoreTokens(); idx++) {
+ ParameterImpl p = new ParameterImpl();
+ p.setName(tokenizer.nextToken());
+ p.setIndex(idx);
+ addParameter(p);
+ }
+ }
+
+}