diff options
author | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-11 23:11:48 +0000 |
---|---|---|
committer | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-11 23:11:48 +0000 |
commit | ece4fd35da7b7fc76264776f81705e6b5b52d3e0 (patch) | |
tree | 962794e2a2b1ab91a02c41e4927a527cade83959 /sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache | |
parent | 76e9f96ca7f494088fe3af5a46ad0d153e961008 (diff) |
Moving 1.x branches
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@835140 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache')
66 files changed, 6551 insertions, 0 deletions
diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/Command.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/Command.java new file mode 100644 index 0000000000..9987b7634d --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/Command.java @@ -0,0 +1,67 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb; + +import commonj.sdo.DataObject; + +/** + * A Command is used to execute a read or write to a database + */ +public interface Command { + + /** + * Performs the function defined by the command + */ + public void execute(); + + /** + * Performs the function defined by the command and return the results in + * the root DataObject + * + * @return the root DataObject + */ + public DataObject executeQuery(); + + /** + * Sets the value of the associated Parameter + * + * @param index + * the index of the Parameter + * @param value + * the value for the Parameter + */ + public void setParameter(int index, Object value); + + /** + * Returns the value of the associated Parameter + * + * @param index + * the index of the Parameter + * @return the value of the Parameter + */ + public Object getParameter(int index); + + + /** + * Returns the value of the database-generated key. This method is specific to an "insert" + * command and will be valid only after the command has been executed. + * + * @return the generated key + */ + public int getGeneratedKey(); + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/ConfigHelper.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/ConfigHelper.java new file mode 100644 index 0000000000..3cacd28a69 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/ConfigHelper.java @@ -0,0 +1,73 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb; + +import org.apache.tuscany.das.rdb.config.Config; +import org.apache.tuscany.das.rdb.config.ConfigFactory; +import org.apache.tuscany.das.rdb.config.impl.ConfigFactoryImpl; +import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper; + +/** + * A ConfigHelper is used as an aid in programmatic construction of Config instances. + * Manual contrution fo COnfig is an alternative to providing needed configuration + * information in an XML file + * + */public class ConfigHelper { + + private Config config; + + private MappingWrapper configWrapper; + + private ConfigFactory factory = ConfigFactoryImpl.eINSTANCE; + + public ConfigHelper() { + config = factory.createConfig(); + configWrapper = new MappingWrapper(config); + } + + public ConfigHelper(Config config) { + this.config = config; + configWrapper = new MappingWrapper(config); + } + + public Config newInstance() { + return factory.createConfig(); + } + + public void addPrimaryKey(String columnName) { + configWrapper.addPrimaryKey(columnName); + } + + public void addRelationship(String parentName, String childName) { + configWrapper.addRelationship(parentName, childName); + } + + public void addTable(String name, String propertyName) { + configWrapper.addTable(name, propertyName); + } + + public void addUpdateStatement(String statement, String tableName, String parameters) { + configWrapper.addUpdateCommand(tableName, statement, parameters); + } + + + + public Config getConfig() { + return config; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/Converter.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/Converter.java new file mode 100644 index 0000000000..eb1ed24230 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/Converter.java @@ -0,0 +1,52 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb; + +/** + * A lightweight Table-column <--> DataObject-property converter framework. + * Converters allow a user to insert a transformation between a column value and + * is destination DataObject property value. For example, by default, a VARCHAR + * column will be represented as a String in its corresponding DataObject + * property. A user could insert a converter that transforms the the VARCHAR + * value to an Integer. If this is done then although the column returns + * character data, the DataObject property will be an Integer + * + * + */ +public interface Converter { + + /** + * Transform the columnData object to a new value and possibly new type. + * This should be the invers operation of #getColumnValue + * + * @param columnData + * The column value to transorm + * @return Returns the transformed value + */ + public Object getPropertyValue(Object columnData); + + /** + * Transform the columnData object to a new value and possibly new type. + * This should be the invers operation of #getPropertyValue + * + * @param propertyData + * The property value to transform + * @return Returns the transformed value + */ + public Object getColumnValue(Object propertyData); + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/DAS.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/DAS.java new file mode 100644 index 0000000000..24c39f5add --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/DAS.java @@ -0,0 +1,53 @@ +package org.apache.tuscany.das.rdb; + +import org.apache.tuscany.das.rdb.impl.DASFactoryImpl; + +import commonj.sdo.DataObject; + +/** + * A CommandGroup represents a set of {@link Command} and single + * {@link ApplyChangesCommand} that are created from a common config file. + * + * + */ +public interface DAS { + + public static DASFactory FACTORY = new DASFactoryImpl(); + + /** + * The change history is scanned and modifications to the graph of data + * objects are flushed to the database. + * + * @param root + * the topmost containing data object + */ + public void applyChanges(DataObject root); + + + /** + * Gets the named command from this factory's inventory + * + * @param name + * The identifying name of the requested command + * @return Returns the identified command + */ + public Command getCommand(String name); + + + /** + * If the CommandGroup is managing connections then this method + * must be called when the client is done with the instance. + * + */ + public void releaseResources(); + + /** + * Creates a Command based on the provided SQL statement + * + * @param sql + * The SQL statement + * @return returns a Command instance + */ + public Command createCommand(String sql); + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/DASFactory.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/DASFactory.java new file mode 100644 index 0000000000..32e9b065ab --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/DASFactory.java @@ -0,0 +1,74 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb; + +import java.io.InputStream; +import java.sql.Connection; + +import org.apache.tuscany.das.rdb.config.Config; + +/** + * A DASFactory produces {@link DAS} instances. + * + * + */ +public interface DASFactory { + + /** + * Creates a DAS based on the provided config file stream + * + * @param configStream + * A stream over a DAS config file + * @return returns a DAS instance + */ + public DAS createDAS(InputStream configStream); + + /** + * Creates a DAS based on the provide config file stream and connection + * @param configStream + * @param connection + * @return + */ + public DAS createDAS(InputStream configStream, Connection connection); + + /** + * Creates a DAS based on the provided config + * + * @param config + * A DAS config object + * @return returns a DAS instance + */ + public DAS createDAS(Config config); + + /** + * Creates a DAS based on the provided config and connection + * @param config + * @param connection + * @return + */ + public DAS createDAS(Config config, Connection connection); + + /** + * Creates a DAS based on the provided connection + * @param connection + * @return + */ + public DAS createDAS(Connection connection); + + +} + diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/Pager.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/Pager.java new file mode 100644 index 0000000000..4edb447e31 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/Pager.java @@ -0,0 +1,62 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb; + +import commonj.sdo.DataObject; + +/** + * An iterator-like interface to conveniently move through chunks of data. The + * idea is that a Pager works with a read Command. The read command returns a + * large amount of data and the client wants to work with chunks of it at a + * time. So the Pager is created on the command and each call to next returns + * the next chunk of data. This is done completely disconnected. No cursor is + * maintained between calls to #next. + * + * TODO - This is very preliminary. We need to look at this interface in the + * context of disonnected scenarios such as a web app. The Pager instance will + * probably be saved in session so it must be very light and cannot reference a + * connection. Also, we probably need to define a factory or add a method to set + * page size. + * + * + */ +public interface Pager { + + /** + * Get the next page of data + * + * @return the next page of data + */ + public DataObject next(); + + /** + * Get the page prior to the last page returned + * + * @return the previous page + */ + public DataObject previous(); + + /** + * Return a specific identified page. + * + * @param page + * The number of the page to return + * @return the indicated page + */ + public DataObject getPage(int page); + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java new file mode 100644 index 0000000000..b1495be4da --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java @@ -0,0 +1,380 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.config.wrapper; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.apache.tuscany.das.rdb.config.Column; +import org.apache.tuscany.das.rdb.config.Config; +import org.apache.tuscany.das.rdb.config.ConfigFactory; +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.Update; +import org.apache.tuscany.das.rdb.config.impl.ConfigFactoryImpl; +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.Property; + +public class MappingWrapper { + + private static final ConfigFactory factory = ConfigFactoryImpl.eINSTANCE; + + private static final boolean debug = false; + + private Config config; + + public MappingWrapper() { + // Empty Constructor + } + + public MappingWrapper(Config mapping) { + this.config = mapping; + } + + public Config getConfig() { + return this.config; + } + + public Table getTable(String tableName) { + if (config == null) + return null; + DebugUtil.debugln(getClass(), debug, "Looking for table " + tableName); + Iterator i = config.getTable().iterator(); + while (i.hasNext()) { + Table t = (Table) i.next(); + if (tableName.equals(t.getTableName())) + return t; + } + + return null; + } + + public Table getTableByTypeName(String typeName) { + if (config == null) + return null; + DebugUtil.debugln(getClass(), debug, "Looking for table by property: " + typeName); + Iterator i = config.getTable().iterator(); + while (i.hasNext()) { + Table t = (Table) i.next(); + TableWrapper wrapper = new TableWrapper(t); + if (typeName.equals(wrapper.getTypeName())) + return t; + } + return null; + + // throw new RuntimeException("Table with property name " + name + // + " not found."); + + } + + public void addRelationship(String parentName, String childName) { + + if (config == null) + config = factory.createConfig(); + + QualifiedColumn parent = new QualifiedColumn(parentName); + QualifiedColumn child = new QualifiedColumn(childName); + + Relationship r = factory.createRelationship(); + r.setName(child.getTableName()); + r.setPrimaryKeyTable(parent.getTableName()); + r.setForeignKeyTable(child.getTableName()); + DebugUtil.debugln(getClass(), debug, "Created relationship from " + r.getPrimaryKeyTable() + " to " + + r.getForeignKeyTable() + " named " + r.getName()); + + KeyPair pair = factory.createKeyPair(); + pair.setPrimaryKeyColumn(parent.getColumnName()); + pair.setForeignKeyColumn(child.getColumnName()); + + r.getKeyPair().add(pair); + r.setMany(true); + + config.getRelationship().add(r); + + } + + + + public void addPrimaryKey(String columnName) { + addPrimaryKey(Collections.singletonList(columnName)); + } + + public void addPrimaryKey(List columnNames) { + if (config == null) + config = factory.createConfig(); + + Iterator i = columnNames.iterator(); + while (i.hasNext()) { + String columnName = (String) i.next(); + + QualifiedColumn pkColumn = new QualifiedColumn(columnName); + Table t = findOrCreateTable(pkColumn.getTableName()); + Column c = findOrCreateColumn(t, pkColumn.getColumnName()); + c.setPrimaryKey(true); + } + } + + public String getTableTypeName(String tableName) { + Table t = getTable(tableName); + if (t == null) + return tableName; + String propertyName = t.getTypeName(); + + if (propertyName == null) + return tableName; + + return propertyName; + } + + public Column getColumn(Table t, String columnName) { + if (t == null) + return null; + Iterator i = t.getColumn().iterator(); + while (i.hasNext()) { + Column c = (Column) i.next(); + if (c.getColumnName().equals(columnName)) { + return c; + } + } + DebugUtil + .debugln(getClass(), debug, "WARNING: Could not find column " + columnName + " in table " + t.getTableName()); + return null; + } + + public Column getColumnByPropertyName(Table t, String propertyName) { + if (t == null) + return null; + Iterator i = t.getColumn().iterator(); + while (i.hasNext()) { + Column c = (Column) i.next(); + if (c.getColumnName().equals(propertyName)) + return c; + if (c.getPropertyName() != null && c.getPropertyName().equals(propertyName)) + return c; + } + DebugUtil.debugln(getClass(), debug, "WARNING: Could not find column " + propertyName + " in table " + + t.getTableName()); + return null; + } + + public String getColumnPropertyName(String tableName, String columnName) { + Table t = getTable(tableName); + Column c = getColumn(t, columnName); + if (c == null) + return columnName; + + String propertyName = c.getPropertyName(); + if (propertyName == null) + return c.getColumnName(); + + return propertyName; + } + + public void addCollisionColumn(String columnName) { + + if (config == null) + config = factory.createConfig(); + + QualifiedColumn occColumn = new QualifiedColumn(columnName); + Table t = findOrCreateTable(occColumn.getTableName()); + Column c = findOrCreateColumn(t, occColumn.getColumnName()); + c.setCollision(true); + + config.getTable().add(t); + } + + public void addTable(String tableName, String typeName) { + Table table = getTable(tableName); + if (table != null) + throw new RuntimeException("Table " + tableName + "already exists"); + + table = ConfigFactoryImpl.eINSTANCE.createTable(); + table.setTableName(tableName); + table.setTypeName(typeName); + config.getTable().add(table); + + } + + private Table findOrCreateTable(String tableName) { + Table table = getTable(tableName); + if (table == null) { + table = ConfigFactoryImpl.eINSTANCE.createTable(); + table.setTableName(tableName); + config.getTable().add(table); + } + return table; + + } + + private Column findOrCreateColumn(Table t, String name) { + Iterator i = t.getColumn().iterator(); + while (i.hasNext()) { + Column c = (Column) i.next(); + if (name.equals(c.getColumnName())) + return c; + } + + Column c = ConfigFactoryImpl.eINSTANCE.createColumn(); + c.setColumnName(name); + t.getColumn().add(c); + return c; + } + + public boolean hasRecursiveRelationships() { + if (config != null) { + Iterator i = getConfig().getRelationship().iterator(); + while (i.hasNext()) { + Relationship r = (Relationship) i.next(); + if (r.getPrimaryKeyTable().equals(r.getForeignKeyTable())) + return true; + } + } + return false; + } + + public Collection getRelationshipsByChildTable(String name) { + ArrayList results = new ArrayList(); + if (config != null) { + Iterator i = getConfig().getRelationship().iterator(); + while (i.hasNext()) { + Relationship r = (Relationship) i.next(); + if (name.equals(r.getForeignKeyTable())) + results.add(r); + } + } + return results; + } + + // TODO optimize + public ArrayList getInsertOrder() { + DebugUtil.debugln(getClass(), debug, "Getting insert order"); + ArrayList inserts = new ArrayList(); + HashMap parentToChild = new HashMap(); + + ArrayList parents = new ArrayList(); + ArrayList children = new ArrayList(); + if (config != null) { + Iterator i = getConfig().getRelationship().iterator(); + while (i.hasNext()) { + Relationship r = (Relationship) i.next(); + parents.add(r.getPrimaryKeyTable()); + children.add(r.getForeignKeyTable()); + parentToChild.put(r.getPrimaryKeyTable(), r.getForeignKeyTable()); + } + + while (parents.size() > 0) { + String parent = (String) parents.get(0); + if (!children.contains(parent)) { + if (!inserts.contains(parent)) + inserts.add(parent); + + String child = (String) parentToChild.get(parent); + if (!inserts.contains(child)) + inserts.add(child); + + parents.remove(parent); + children.remove(child); + } else { + parents.add(parents.remove(0)); + } + } + inserts.addAll(children); + + } + + DebugUtil.debugln(getClass(), debug, inserts); + return inserts; + } + + public ArrayList getDeleteOrder() { + ArrayList deleteOrder = new ArrayList(); + deleteOrder.addAll(getInsertOrder()); + Collections.reverse(deleteOrder); + return deleteOrder; + } + + public void addConverter(String name, String converter) { + if (config == null) + config = factory.createConfig(); + + QualifiedColumn column = new QualifiedColumn(name); + Table t = findOrCreateTable(column.getTableName()); + Column c = findOrCreateColumn(t, column.getColumnName()); + c.setConverterClassName(converter); + + } + + public String getConverter(String tableName, String columnName) { + Table t = getTable(tableName); + Column c = getColumn(t, columnName); + if (c != null) + return c.getConverterClassName(); + return null; + } + + public HashMap getConverters(Table table) { + HashMap converters = new HashMap(); + + Iterator columns = table.getColumn().iterator(); + while (columns.hasNext()) { + Column c = (Column) columns.next(); + if (c.getConverterClassName() != null) { + String property = c.getPropertyName(); + if (property == null) + property = c.getColumnName(); + converters.put(property, c.getConverterClassName()); + } + } + return converters; + } + + public Relationship getRelationshipByReference(Property ref) { + Iterator i = config.getRelationship().iterator(); + while (i.hasNext()) { + Relationship r = (Relationship) i.next(); + if (ref.getName().equals(r.getName()) || ref.getOpposite().getName().equals(r.getName())) + return r; + } + throw new RuntimeException("Could not find relationship " + ref.getName() + " in the configuration"); + } + + public Relationship getRelationshipByName(String name) { + Iterator i = config.getRelationship().iterator(); + while (i.hasNext()) { + Relationship r = (Relationship) i.next(); + if (name.equals(r.getName())) + return r; + } + throw new RuntimeException("Could not find relationship " + name + " in the configuration"); + } + + public void addUpdateCommand(String tableName, String statement, String parameters) { + Table table = findOrCreateTable(tableName); + Update update = ConfigFactoryImpl.eINSTANCE.createUpdate(); + update.setSql(statement); + update.setParameters(parameters); + table.setUpdate(update); + + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/QualifiedColumn.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/QualifiedColumn.java new file mode 100644 index 0000000000..6babe0c349 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/QualifiedColumn.java @@ -0,0 +1,41 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.config.wrapper; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + +public class QualifiedColumn { + + private final String tableName; + private final String columnName; + private static boolean debug = false; + + public QualifiedColumn(String name) { + tableName = name.substring(0, name.indexOf('.')); + columnName = name.substring(name.indexOf('.') + 1); + DebugUtil.debugln(getClass(), debug, tableName); + DebugUtil.debugln(getClass(), debug, columnName); + } + + public String getTableName() { + return this.tableName; + } + + public String getColumnName() { + return this.columnName; + } +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/RelationshipWrapper.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/RelationshipWrapper.java new file mode 100644 index 0000000000..14403367d8 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/RelationshipWrapper.java @@ -0,0 +1,44 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.config.wrapper; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + +import org.apache.tuscany.das.rdb.config.KeyPair; +import org.apache.tuscany.das.rdb.config.Relationship; + +public class RelationshipWrapper { + + private Relationship relationship; + + public RelationshipWrapper(Relationship r) { + this.relationship = r; + } + + public Collection getForeignKeys() { + ArrayList keys = new ArrayList(); + Iterator i = this.relationship.getKeyPair().iterator(); + while ( i.hasNext()) { + KeyPair pair = (KeyPair) i.next(); + keys.add(pair.getForeignKeyColumn()); + } + return keys; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/TableWrapper.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/TableWrapper.java new file mode 100644 index 0000000000..764a0851a0 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/TableWrapper.java @@ -0,0 +1,126 @@ +/** +* +* Copyright 2005 The Apache Software Foundation or its licensors, as applicable. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.apache.tuscany.das.rdb.config.wrapper; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + +import org.apache.tuscany.das.rdb.config.Column; +import org.apache.tuscany.das.rdb.config.Table; + +public class TableWrapper { + + private Table table; + + public TableWrapper(Table table) { + this.table = table; + } + + public String getTypeName() { + return table.getTypeName() == null ? table.getTableName() : table + .getTypeName(); + } + + public Collection getPrimaryKeyNames() { + ArrayList pkNames = new ArrayList(); + Iterator i = table.getColumn().iterator(); + while (i.hasNext()) { + Column c = (Column) i.next(); + if (c.isPrimaryKey()) + pkNames.add(c.getColumnName()); + } + return pkNames; + } + + public Collection getPrimaryKeyProperties() { + + ArrayList keyProperties = new ArrayList(); + Iterator columns = table.getColumn().iterator(); + while (columns.hasNext()) { + Column c = (Column) columns.next(); + if (c.isPrimaryKey()) { + keyProperties.add(getColumnPropertyName(c)); + } + } + + return keyProperties; + } + + private String getColumnPropertyName(Column c) { + if (c.getPropertyName() != null) + return c.getPropertyName(); + else + return c.getColumnName(); + } + + public boolean isGeneratedColumnProperty(String name) { + Column c = getColumnByPropertyName(name); + return c == null ? false : c.isGenerated(); + } + + + public String getConverter(String propertyName) { + Column c = getColumnByPropertyName(propertyName); + return (c == null) ? null : c.getConverterClassName(); + } + + public Column getColumnByPropertyName(String propertyName) { + Iterator columns = table.getColumn().iterator(); + while (columns.hasNext()) { + Column c = (Column) columns.next(); + String property = c.getPropertyName(); + if (property == null) + property = c.getColumnName(); + if (propertyName.equals(property)) + return c; + } + + return null; + } + + public Column getCollisionColumn() { + Iterator columns = table.getColumn().iterator(); + while (columns.hasNext()) { + Column c = (Column) columns.next(); + if ( c.isCollision() ) + return c; + } + + return null; + + } + + public String getCollisionColumnPropertyName() { + Column c = getCollisionColumn(); + if ( c.getPropertyName() != null ) + return c.getPropertyName(); + else + return c.getColumnName(); + } + + public String getManagedColumnPropertyName() { + Iterator i = table.getColumn().iterator(); + while (i.hasNext()) { + Column c = (Column) i.next(); + if (c.isManaged()) + return c.getPropertyName() == null ? c.getColumnName() : c.getPropertyName(); + } + return null; + + } +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/BaseGenerator.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/BaseGenerator.java new file mode 100644 index 0000000000..50beec06d7 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/BaseGenerator.java @@ -0,0 +1,18 @@ +package org.apache.tuscany.das.rdb.generator.impl; + +import org.apache.tuscany.das.rdb.Converter; + +public class BaseGenerator { + + protected Converter getConverter(String converter) { + if ( converter != null ) { + try { + return (Converter) Thread.currentThread().getContextClassLoader().loadClass(converter).newInstance(); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + return null; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/DeleteGenerator.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/DeleteGenerator.java new file mode 100644 index 0000000000..c83032698a --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/DeleteGenerator.java @@ -0,0 +1,80 @@ +/** +* +* Copyright 2005 The Apache Software Foundation or its licensors, as applicable. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.apache.tuscany.das.rdb.generator.impl; + +import java.util.Iterator; + +import org.apache.tuscany.das.rdb.config.Table; +import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper; +import org.apache.tuscany.das.rdb.impl.DeleteCommandImpl; +import org.apache.tuscany.das.rdb.impl.ParameterImpl; +import org.apache.tuscany.das.rdb.impl.SDODataTypes; +import org.apache.tuscany.das.rdb.util.DebugUtil; + +public class DeleteGenerator extends BaseGenerator { + + public static final DeleteGenerator instance = new DeleteGenerator(); + + private static final boolean debug = false; + + private DeleteGenerator() { + super(); + } + + private String getDeleteStatement(Table t) { + TableWrapper table = new TableWrapper(t); + + StringBuffer statement = new StringBuffer(); + statement.append("delete from "); + statement.append(t.getTableName()); + statement.append(" where "); + + Iterator names = table.getPrimaryKeyNames().iterator(); + Iterator properties = table.getPrimaryKeyProperties().iterator(); + while (names.hasNext() && properties.hasNext()) { + String name = (String) names.next(); + statement.append(name); + statement.append(" = ?"); + if (names.hasNext() && properties.hasNext()) + statement.append(" and "); + } + + DebugUtil.debugln(getClass(), debug, statement.toString()); + return statement.toString(); + } + + public DeleteCommandImpl getDeleteCommand(Table t) { + TableWrapper tw = new TableWrapper(t); + DeleteCommandImpl deleteCommand = new DeleteCommandImpl(getDeleteStatement(t)); + + Iterator i = tw.getPrimaryKeyProperties().iterator(); + for(int idx=1; i.hasNext(); idx++) { + String property = (String) i.next(); + ParameterImpl p = new ParameterImpl(); + p.setName(property); + p.setType(SDODataTypes.OBJECT); + p.setConverter(getConverter(tw.getConverter(property))); + p.setIndex(idx); + deleteCommand.addParameter(p); + } + return deleteCommand; + } + + + +} + diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/InsertGenerator.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/InsertGenerator.java new file mode 100644 index 0000000000..183d1800d5 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/InsertGenerator.java @@ -0,0 +1,147 @@ +/** +* +* Copyright 2005 The Apache Software Foundation or its licensors, as applicable. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.apache.tuscany.das.rdb.generator.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.apache.tuscany.das.rdb.config.Relationship; +import org.apache.tuscany.das.rdb.config.Table; +import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper; +import org.apache.tuscany.das.rdb.config.wrapper.RelationshipWrapper; +import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper; +import org.apache.tuscany.das.rdb.impl.InsertCommandImpl; +import org.apache.tuscany.das.rdb.impl.ParameterImpl; +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.DataObject; +import commonj.sdo.Property; + +public class InsertGenerator extends BaseGenerator { + + public static final InsertGenerator instance = new InsertGenerator(); + + private static final boolean debug = false; + + private InsertGenerator() { + super(); + } + + public InsertCommandImpl getInsertCommand(MappingWrapper config, + DataObject changedObject, Table t) { + ArrayList parameters = new ArrayList(); + TableWrapper table = new TableWrapper(t); + StringBuffer statement = new StringBuffer("insert into "); + statement.append(t.getTableName()); + + Iterator i = getAttributeProperties(changedObject, config).iterator(); + + ArrayList attributes = new ArrayList(); + while (i.hasNext()) { + Property attr = (Property) i.next(); + if (!table.isGeneratedColumnProperty(attr.getName())) { + attributes.add(attr.getName()); + parameters.add(changedObject.getType().getProperty( + attr.getName())); + } + } + + statement.append("("); + Iterator attrs = attributes.iterator(); + while (attrs.hasNext()) { + String name = (String) attrs.next(); + statement.append(""); + statement.append(name); + if (attrs.hasNext()) + statement.append(", "); + else + statement.append(")"); + } + + statement.append(" values ("); + for (int idx = 1; idx <= attributes.size(); idx++) { + statement.append('?'); + if (idx < attributes.size()) + statement.append(", "); + else + statement.append(")"); + } + + InsertCommandImpl cmd = new InsertCommandImpl(statement.toString()); + Iterator params = parameters.iterator(); + for (int idx = 1; params.hasNext(); idx++) { + Property property = (Property) params.next(); + ParameterImpl p = new ParameterImpl(); + p.setName(property.getName()); + p.setType(property.getType()); + p.setConverter(getConverter(table.getConverter(property.getName()))); + p.setIndex(idx); + cmd.addParameter(p); + + } + DebugUtil.debugln(getClass(), debug, statement.toString()); + return cmd; + + } + + private List getAttributeProperties(DataObject obj, MappingWrapper config) { + ArrayList fields = new ArrayList(); + Iterator i = obj.getType().getProperties().iterator(); + while (i.hasNext()) { + Property p = (Property) i.next(); + if (p.getType().isDataType()) { + if (obj.isSet(p)) + fields.add(p); + } else { + if ( obj.isSet(p) ) { + Relationship relationship = config.getRelationshipByReference(p); + if ( p.getOpposite().isMany() || (hasState(config, relationship, obj))) { + RelationshipWrapper r = new RelationshipWrapper( + relationship); + Iterator keys = r.getForeignKeys().iterator(); + while (keys.hasNext()) { + String key = (String) keys.next(); + Property keyProp = obj.getType().getProperty(key); + fields.add(keyProp); + } + } + + } + } + } + + return fields; + + } + + private boolean hasState(MappingWrapper config, Relationship rel, DataObject changedObject) { + + if ( !rel.isMany()) { + Table t = config.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; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/UpdateGenerator.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/UpdateGenerator.java new file mode 100644 index 0000000000..3aeb47c4a7 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/generator/impl/UpdateGenerator.java @@ -0,0 +1,192 @@ +/** +* +* Copyright 2005 The Apache Software Foundation or its licensors, as applicable. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.apache.tuscany.das.rdb.generator.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.tuscany.das.rdb.config.Column; +import org.apache.tuscany.das.rdb.config.Table; +import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper; +import org.apache.tuscany.das.rdb.config.wrapper.RelationshipWrapper; +import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper; +import org.apache.tuscany.das.rdb.impl.ManagedParameterImpl; +import org.apache.tuscany.das.rdb.impl.OptimisticWriteCommandImpl; +import org.apache.tuscany.das.rdb.impl.ParameterImpl; +import org.apache.tuscany.das.rdb.impl.UpdateCommandImpl; +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.ChangeSummary; +import commonj.sdo.DataObject; +import commonj.sdo.Property; +import commonj.sdo.Type; + +public class UpdateGenerator extends BaseGenerator { + + private boolean debug = false; + + public static UpdateGenerator instance = new UpdateGenerator(); + + private UpdateGenerator() { + super(); + } + + public UpdateCommandImpl getUpdateCommand(MappingWrapper mapping, DataObject changedObject, Table table) { + ArrayList updatedProperties = new ArrayList(); + ArrayList managedProperties = new ArrayList(); + ArrayList whereClauseProperties = new ArrayList(); + Type type = changedObject.getType(); + TableWrapper t = new TableWrapper(table); + StringBuffer statement = new StringBuffer("update "); + statement.append(table.getTableName()); + statement.append(" set "); + + + ChangeSummary summary = changedObject.getDataGraph().getChangeSummary(); + Iterator i = getChangedFields(mapping, summary, changedObject).iterator(); + + while (i.hasNext()) { + Property property = (Property) i.next(); + Column c = t.getColumnByPropertyName(property.getName()); + if ((c != null) && (c.isCollision() || c.isPrimaryKey())) { + // get rid of comma if OCC or PK is last field + if (!i.hasNext()) { + statement + .delete(statement.length() - 2, statement.length()); + } + } else { + updatedProperties.add(property); + statement.append(c == null ? property.getName() : c.getColumnName()); + statement.append(" = ?"); + if (i.hasNext()) + statement.append(", "); + } + } + + if ( t.getManagedColumnPropertyName() != null ) { + statement.append(", "); + statement.append(t.getManagedColumnPropertyName()); + statement.append(" = ?"); + managedProperties.add(changedObject.getProperty(t.getManagedColumnPropertyName())); + } + statement.append(" where "); + + Iterator names = t.getPrimaryKeyNames().iterator(); + Iterator pkProperties = t.getPrimaryKeyProperties().iterator(); + while (names.hasNext() && pkProperties.hasNext()) { + String name = (String) names.next(); + String property = (String) pkProperties.next(); + statement.append(name); + statement.append(" = ?"); + if (names.hasNext() && pkProperties.hasNext()) + statement.append(" and "); + whereClauseProperties.add(type.getProperty(property)); + } + + if (t.getCollisionColumn() != null) { + statement.append(" and "); + statement.append(t.getCollisionColumn().getColumnName()); + statement.append(" = ?"); + whereClauseProperties.add(type.getProperty(t.getCollisionColumnPropertyName())); + } + + + UpdateCommandImpl updateCommand; + if ( t.getCollisionColumn() != null ) + updateCommand = new OptimisticWriteCommandImpl(statement.toString()); + else + updateCommand = new UpdateCommandImpl(statement.toString()); + + + int idx = 1; + Iterator params = updatedProperties.iterator(); + while ( params.hasNext()) { + Property p = (Property)params.next(); + updateCommand.addParameter(createParameter(t, p, idx++)); + } + + params = managedProperties.iterator(); + while ( params.hasNext()) { + Property p = (Property)params.next(); + updateCommand.addParameter(createManagedParameter(t, p, idx++)); + } + + params = whereClauseProperties.iterator(); + while ( params.hasNext()) { + Property p = (Property)params.next(); + updateCommand.addParameter(createParameter(t, p, idx++)); + } + + DebugUtil.debugln(getClass(), debug, statement.toString()); + return updateCommand; + } + + + + private List getChangedFields(MappingWrapper mapping, ChangeSummary summary, DataObject obj) { + ArrayList changes = new ArrayList(); + Iterator i = summary.getOldValues(obj).iterator(); + while (i.hasNext()) { + ChangeSummary.Setting setting = (ChangeSummary.Setting) i.next(); + if (setting.getProperty().getType().isDataType()) { + changes.add(setting.getProperty()); + } else { + Property ref = setting.getProperty(); + if ( !ref.isMany() ) { + RelationshipWrapper r = new RelationshipWrapper(mapping.getRelationshipByReference(ref)); + + Iterator keys = r.getForeignKeys().iterator(); + while ( keys.hasNext()) { + String key = (String) keys.next(); + Property p = obj.getType().getProperty(key); + changes.add(p); + } + } + + } + } + return changes; + } + + + + private ParameterImpl createManagedParameter(TableWrapper table, Property property, int idx) { + ParameterImpl param = new ManagedParameterImpl(); + param.setName(property.getName()); + param.setType(property.getType()); + param.setConverter(getConverter(table.getConverter(property.getName()))); + if ( idx != -1) + param.setIndex(idx); + + return param; + } + + private ParameterImpl createParameter(TableWrapper table, Property property, int idx) { + ParameterImpl param = new ParameterImpl(); + param.setName(property.getName()); + param.setType(property.getType()); + param.setConverter(getConverter(table.getConverter(property.getName()))); + if ( idx != -1) + param.setIndex(idx); + + return param; + } + + +} + diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DataObjectMaker.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DataObjectMaker.java new file mode 100644 index 0000000000..9279aea2c7 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DataObjectMaker.java @@ -0,0 +1,116 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.impl; + +import java.util.Iterator; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.DataObject; +import commonj.sdo.Property; +import commonj.sdo.Type; +import commonj.sdo.helper.DataFactory; + +public class DataObjectMaker { + + private final DataObject rootObject; + + private boolean debug = false; + + public DataObjectMaker(DataObject root) { + this.rootObject = root; + } + + /** + * @param tableData + * @return + */ + public DataObject createAndAddDataObject(TableData tableData, + ResultMetadata resultMetadata) { + // Get a Type from the package and create a standalone DataObject + + DebugUtil.debugln(getClass(), this.debug, "Looking for Type for " + + tableData.getTableName()); + + Type tableClass = findTableTypeByPropertyName(tableData.getTableName()); + + if (tableClass == null) + throw new RuntimeException("An SDO Type with name " + + tableData.getTableName() + " was not found"); + + DataObject obj = DataFactory.INSTANCE.create(tableClass); + + // Now, check to see if the root data object has a containment reference + // to this EClass. If so, add it to the graph. If not, it will be taken + // care + // of when we process relationships + + Iterator i = this.rootObject.getType().getProperties().iterator(); + while (i.hasNext()) { + Property p = (Property) i.next(); + + if (p.isContainment() && p.getType().equals(tableClass)) { + if (p.isMany()) + rootObject.getList(p).add(obj); + // TODO This was a performance optimization for EMF in SDO 1.1, + // check to see if there is + // something equivalent in SDO 2.0 + // ((InternalEList) this.dataGraph.eGet(ref)).addUnique(obj); + else + this.rootObject.set(p, obj); + } + + } + + Iterator columnNames = resultMetadata.getColumnNames( + tableData.getTableName()).iterator(); + while (columnNames.hasNext()) { + String columnName = (String) columnNames.next(); + + Property p = findProperty(obj.getType(), columnName); + Object value = tableData.getColumnData(columnName); + + obj.set(p, value); + } + + return obj; + } + + // temporary, ignoring case + private Property findProperty(Type type, String columnName) { + Iterator properties = type.getProperties().iterator(); + while (properties.hasNext()) { + Property p = (Property) properties.next(); + if (columnName.equalsIgnoreCase(p.getName())) + return p; + } + return null; + } + + private Type findTableTypeByPropertyName(String tableName) { + Iterator i = rootObject.getType().getProperties().iterator(); + while (i.hasNext()) { + Property p = (Property) i.next(); + if (tableName.equals(p.getType().getName())) + return p.getType(); + } + + return null; + } + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DefaultConverter.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DefaultConverter.java new file mode 100644 index 0000000000..54c536d95c --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/DefaultConverter.java @@ -0,0 +1,91 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.impl; + +import java.sql.Blob; +import java.sql.SQLException; + +import org.apache.tuscany.das.rdb.Converter; + + +public class DefaultConverter implements Converter { + + public DefaultConverter() { + super(); + } + + public Object getColumnValue(Object data) { + return data; + } + + public Object getPropertyValue(Object data) { +// if (type.isInstance(data)) +// return data; +// +// if ( data == null ) +// return null; +// +// String name = type.getInstanceClass().getName(); +// if (name == "java.lang.Byte" || name == "byte") { +// return new Byte(data.toString()); +// } +// +// else if (name == "java.lang.Double" || name == "double") { +// return new Double(data.toString()); +// } +// +// else if (name == "java.lang.Float" || name == "float") { +// return new Float(data.toString()); +// } +// +// else if (name == "java.lang.Integer" || name == "int") { +// return new Integer(data.toString()); +// } +// +// else if (name == "java.lang.Long" || name == "long") { +// return new Long(data.toString()); +// } +// +// else if (name == "java.lang.Short" || name == "short") { +// return new Short(data.toString()); +// } +// +// else if (name == "java.lang.String") { +// return String.valueOf(data.toString()); +// } + + if ( data instanceof Blob ) { + Blob b = (Blob) data; + try { + return b.getBytes(1, (int)b.length()); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } else { + return data; + } + + + +// else { +// +// throw new IllegalArgumentException("The database value of type " +// + data.getClass().getName() + " must be converted to type " +// + type.getInstanceClass().getName()); +// } + } +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/GraphBuilderMetadata.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/GraphBuilderMetadata.java new file mode 100644 index 0000000000..0a3bba0c57 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/GraphBuilderMetadata.java @@ -0,0 +1,100 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.impl; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; + +import org.apache.tuscany.das.rdb.config.Config; +import org.apache.tuscany.das.rdb.graphbuilder.schema.ESchemaMaker; +import org.apache.tuscany.das.rdb.impl.ResultSetShape; +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.Type; + + +/** + */ +public class GraphBuilderMetadata { + + private Config mappingModel; + private final Collection resultSets = new ArrayList(); + private boolean debug = false; + private String typeURI; + + + public GraphBuilderMetadata(Collection results, Config model, ResultSetShape shape) throws SQLException { + this.mappingModel = model; + if (model != null) { + this.typeURI = model.getDataObjectModel(); + } + + Iterator i = results.iterator(); + while (i.hasNext()) { + ResultSet rs = (ResultSet) i.next(); + ResultMetadata resultMetadata = new ResultMetadata(rs, mappingModel, shape); + resultSets.add(resultMetadata); + } + + DebugUtil.debugln(getClass(), debug, "Mapping model: " + mappingModel); + } + + + public Collection getResultMetadata() { + return this.resultSets; + } + + + public boolean hasMappingModel() { + return mappingModel == null ? false : true; + } + + + /** + * @return + */ + + public Collection getRelationships() { + if (!hasMappingModel()) { + DebugUtil.debugln(getClass(), debug, "No relationships to return"); + return Collections.EMPTY_LIST; + } + + return mappingModel.getRelationship(); + } + + + /** + * @return + */ + public Type getSchema() { + ESchemaMaker schemaMaker = new ESchemaMaker(this); + if ( this.typeURI == null ) { + return schemaMaker.createTypes(); + } else { + return schemaMaker.createTypes(this.typeURI); + } + } + + public Config getMapping() { + return this.mappingModel; + } +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java new file mode 100644 index 0000000000..142aee5c60 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java @@ -0,0 +1,105 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.DataObject; + + + +/** + * + * Used to store and look up table objects based on primary key + * This could be a lot more efficient if we could use LinkedHashMap from JDK 1.4 + */ +public class MultiTableRegistry implements TableRegistry { + + private HashMap tableNameMap; + private HashMap tableValueMap; + private boolean debug = false; + + + public MultiTableRegistry() { + tableNameMap = new HashMap(); + tableValueMap = new HashMap(); + } + + + + /** + * Get the table with the specified name and primary key + * @param tableName + * @param primaryKey + * @return EDataObject + */ + public DataObject get(String tableName, List primaryKey) { + if ( debug ) { + DebugUtil.debugln(getClass(), debug, "Looking for table " + tableName + " with PK " + primaryKey); + DebugUtil.debugln(getClass(), debug, ("\tReturning " + getPkMap(tableName).get(primaryKey))); + } + return (DataObject) getPkMap(tableName).get(primaryKey); + } + + /** + * Add the table with the specified name and primary key + * @param tableName + * @param primaryKey + * @param value + */ + public void put(String tableName, List primaryKey, DataObject value) { + if ( getPkMap(tableName).put(primaryKey, value) == null ) + getCreateValueList(tableName).add(value); + } + + /** + * Get the HashMap that contains the primary key to table object + * mappings. + * @param tableName + * @return HashMap + */ + private HashMap getPkMap(String tableName) { + HashMap pkMap = (HashMap)tableNameMap.get(tableName); + if ( pkMap == null ) { + pkMap = new HashMap(); + tableNameMap.put(tableName, pkMap); + } + return pkMap; + } + + private List getCreateValueList(String tableName) { + List values = (List) tableValueMap.get(tableName); + if ( values == null ) { + values = new ArrayList(); + tableValueMap.put(tableName, values); + } + return values; + } + + + + public boolean contains(String tableName, List primaryKey) { + return get(tableName,primaryKey) == null ? false : true; + + } + + +}
\ No newline at end of file diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultMetadata.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultMetadata.java new file mode 100644 index 0000000000..a455ed348a --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultMetadata.java @@ -0,0 +1,286 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.impl; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.tuscany.das.rdb.Converter; +import org.apache.tuscany.das.rdb.config.Column; +import org.apache.tuscany.das.rdb.config.Config; +import org.apache.tuscany.das.rdb.config.Table; +import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper; +import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper; +import org.apache.tuscany.das.rdb.impl.ResultSetShape; +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.Type; + +public class ResultMetadata { + + private HashMap tableToColumnMap = new HashMap(); + + private ArrayList typeNames = new ArrayList(); + + private ArrayList propertyNames = new ArrayList(); + + private final ResultSet resultSet; + + private final ResultSetShape resultSetShape; + + private final MappingWrapper mappingWrapper; + + private Converter[] converters; + + private static boolean debug = false; + + public ResultMetadata(ResultSet rs, Config model, ResultSetShape shape) + throws SQLException { + debug("Creating new ResultMetadata with mapping model " + model); + this.resultSet = rs; + this.mappingWrapper = new MappingWrapper(model); + + if (shape == null) + this.resultSetShape = new ResultSetShape(rs.getMetaData()); + else + this.resultSetShape = shape; + + this.converters = new Converter[resultSetShape.getColumnCount()]; + + for (int i = 1; i <= resultSetShape.getColumnCount(); i++) { + String tableName = resultSetShape.getTableName(i); + + String typeName = mappingWrapper + .getTableTypeName(tableName); + String propertyName = mappingWrapper.getColumnPropertyName( + tableName, resultSetShape.getColumnName(i)); + String converterName = mappingWrapper.getConverter(tableName, + resultSetShape.getColumnName(i)); + + converters[i-1] = loadConverter(converterName); + + DebugUtil.debugln(getClass(), debug, "Adding table/column: " + + typeName + "/" + propertyName); + typeNames.add(typeName); + propertyNames.add(propertyName); + + Collection columns = (Collection) tableToColumnMap + .get(typeName); + if (columns == null) + columns = new ArrayList(); + columns.add(propertyName); + tableToColumnMap.put(typeName, columns); + } + + // Add any tables defined in the model but not included in the ResultSet + // to the list of propertyNames + if (model != null) { + Iterator tablesFromModel = model.getTable().iterator(); + while (tablesFromModel.hasNext()) { + TableWrapper t = new TableWrapper((Table) tablesFromModel + .next()); + if (tableToColumnMap.get(t.getTypeName()) == null) + tableToColumnMap.put(t.getTypeName(), + Collections.EMPTY_LIST); + } + } + + if (debug) { + DebugUtil.debugln(getClass(), debug, toString()); + DebugUtil + .debugln(getClass(), debug, this.resultSetShape.toString()); + } + + } + + private Converter loadConverter(String converterName) { + if (converterName != null) { + + try { + + Class converterClazz= Class.forName(converterName, true, Thread.currentThread().getContextClassLoader()); + if(null != converterClazz) + return (Converter) converterClazz.newInstance(); + } catch( Exception ex){ + throw new RuntimeException(ex); + } + + try{ + Class converterClazz = Class.forName(converterName); + if ( converterClazz != null) + return (Converter)converterClazz.newInstance(); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + return new DefaultConverter(); + } + + private void debug(Object string) { + if (debug) + DebugUtil.debugln(getClass(), debug, string); + } + + public String getColumnPropertyName(int i) { + return (String) propertyNames.get(i - 1); + } + + public String getDatabaseColumnName(int i) { + return resultSetShape.getColumnName(i); + } + + public String getTableName(String columnName) { + return (String) typeNames.get(propertyNames + .indexOf(columnName)); + } + + public int getTableSize(String tableName) { + return ((Collection) tableToColumnMap.get(tableName)).size(); + } + + public Type getDataType(String columnName) { + return resultSetShape.getColumnType(propertyNames + .indexOf(columnName)); + } + + public String getTablePropertyName(int i) { + return (String) typeNames.get(i - 1); + } + + public Collection getAllTablePropertyNames() { + return tableToColumnMap.keySet(); + } + + public String toString() { + + StringBuffer result = new StringBuffer(super.toString()); + result.append(" (Table Names: "); + Iterator i = typeNames.iterator(); + while (i.hasNext()) { + String tableName = (String) i.next(); + result.append(' '); + result.append(tableName); + result.append(','); + } + + result.append(" columnNames: "); + + i = propertyNames.iterator(); + while (i.hasNext()) { + String columnName = (String) i.next(); + result.append(' '); + result.append(columnName); + result.append(','); + } + + result.append(" mappingModel: "); + result.append(this.mappingWrapper.getConfig()); + + result.append(" resultSet: "); + result.append(resultSet); + + result.append(" resultSetSize: "); + result.append(resultSetShape.getColumnCount()); + result.append(')'); + return result.toString(); + + } + + /** + * @return + */ + public int getNumberOfTables() { + return tableToColumnMap.keySet().size(); + } + + /** + * Return whether the column at the given position is part of a primary key. + * If we don't have this information, we assume every column is a primary + * key. This results in uniqueness checks using all columns in a table. + * + * @param i + * @return + */ + public boolean isPKColumn(int i) { + if (debug) { + DebugUtil.debugln(getClass(), debug, "Checking to see if " + + getColumnPropertyName(i) + " is a PK column in " + + getTablePropertyName(i)); + } + if (!hasMappingModel()) { + if (debug) + DebugUtil + .debugln(getClass(), debug, + "No mapping model exists, all columns will be considered PK columns"); + return true; + } else { + Table t = mappingWrapper.getTableByTypeName(getTablePropertyName(i)); + if (t == null) + return true; + Column c = mappingWrapper.getColumn(t, getDatabaseColumnName(i)); + + if (c == null) + return false; + + if (c.isPrimaryKey()) + return true; + } + return false; + } + + public boolean hasMappingModel() { + return mappingWrapper.getConfig() == null ? false : true; + } + + /** + * @param i + * @return + */ + public Type getDataType(int i) { + return resultSetShape.getColumnType(i); + } + + /** + * @param tableName + * @return + */ + public Collection getColumnNames(String tableName) { + return (Collection) tableToColumnMap.get(tableName); + } + + public ResultSet getResultSet() { + return this.resultSet; + } + + public int getResultSetSize() { + return resultSetShape.getColumnCount(); + } + + public boolean isRecursive() { + return mappingWrapper.hasRecursiveRelationships(); + } + + public Converter getConverter(int i) { + return converters[i - 1]; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetProcessor.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetProcessor.java new file mode 100644 index 0000000000..6d68162dee --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetProcessor.java @@ -0,0 +1,137 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.impl; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Iterator; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.DataObject; + +/** + * + * A ResultSetProcessor is used to transform the data in a ResultSet into a set + * of inter-related EDataObjects. + */ +public class ResultSetProcessor { + + private TableRegistry registry; + + private GraphBuilderMetadata metadata; + + private boolean debug = false; + + private final DataObjectMaker doMaker; + + public ResultSetProcessor(DataObject g, GraphBuilderMetadata gbmd) { + + this.metadata = gbmd; + if (metadata.getRelationships().size() == 0) + registry = new SingleTableRegistry(); + else + registry = new MultiTableRegistry(); + + doMaker = new DataObjectMaker(g); + + debug(metadata); + + } + + private void debug(Object output) { + DebugUtil.debugln(getClass(), debug, output); + } + + /** + * Process the ResultSet. For each row in the ResultSet, a + * + * @link ResultSetRow object will be created to represent the row as a set + * of EDataObjects. Then, the relevant relationships will be + * constructed between each object in the + * @link ResultSetRow. + * + * @param rs + * The ResultSet + */ + public void processResults(int start, int end) throws SQLException { + + Iterator i = metadata.getResultMetadata().iterator(); + while ( i.hasNext()) { + ResultMetadata resultMetadata = (ResultMetadata)i.next(); + ResultSet results = resultMetadata.getResultSet(); + + processResultSet(results, resultMetadata, start, end); + + //TODO These statements HAVE to be closed or we will have major problems +// results.getStatement().close(); + results.close(); + } + + } + + + private void processResultSet(ResultSet rs, ResultMetadata rsMetadata, + int start, int end) throws SQLException { + + if ( rs.getType() == ResultSet.TYPE_FORWARD_ONLY) { + while (rs.next() && start < end) { + ResultSetRow rsr = new ResultSetRow(rs, rsMetadata); + addRowToGraph(rsr, rsMetadata); + ++start; + } + } else { + while (rs.absolute(start) && start < end) { + ResultSetRow rsr = new ResultSetRow(rs, rsMetadata); + addRowToGraph(rsr, rsMetadata); + ++start; + } + } + } + + /** + * @param row + * @param resultMetadata + */ + private void addRowToGraph(ResultSetRow row, ResultMetadata resultMetadata) { + RowObjects tableObjects = new RowObjects(metadata, registry); + Iterator tables = row.getAllTableData().iterator(); + while (tables.hasNext()) { + TableData rawDataFromRow = (TableData) tables.next(); + + if ( (resultMetadata.hasMappingModel()) && (!rawDataFromRow.hasValidPrimaryKey() ) ) + continue; + + String tableName = rawDataFromRow.getTableName(); + DataObject tableObject = registry.get(tableName, rawDataFromRow + .getPrimaryKeyValues()); + if (tableObject == null) { + tableObject = doMaker.createAndAddDataObject(rawDataFromRow, resultMetadata); + + debug("Putting table " + tableName + " with PK " + rawDataFromRow.getPrimaryKeyValues() + " into registry"); + + registry.put(tableName, rawDataFromRow.getPrimaryKeyValues(), + tableObject); + } + tableObjects.put(tableName, tableObject); + } + + tableObjects.processRelationships(); + + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetRow.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetRow.java new file mode 100644 index 0000000000..f68f48fc06 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/ResultSetRow.java @@ -0,0 +1,169 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.impl; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + + +/** + * + * A ResultSetRow is used to transform a single row of a ResultSet into a set of + * EDataObjects. + */ +public class ResultSetRow { + + private final ResultMetadata metadata; + + private HashMap tableMap = new HashMap(); + + private ArrayList allTableData; + + private boolean debug = false; + + /** + * Method ResultSetRow. + * + * @param rs + * A ResultSet positioned on the desired row + * @param ePackage + * The package used to create EDataObjects + */ + public ResultSetRow(ResultSet rs, ResultMetadata m) throws SQLException { + this.metadata = m; + if (m.isRecursive()) + processRecursiveRow(rs); + else + processRow(rs); + } + + /** + * Processes a single row in the ResultSet Method processRow. + * + * @param rs + */ + private void processRow(ResultSet rs) throws SQLException { + + DebugUtil.debugln(getClass(), debug, ""); + for (int i = 1; i <= metadata.getResultSetSize(); i++) { + Object data = getObject(rs, i); + + TableData table = getRawData(metadata.getTablePropertyName(i)); + DebugUtil.debugln(getClass(), debug, "Adding column: " + + metadata.getColumnPropertyName(i) + "\tValue: " + data + + "\tTable: " + metadata.getTablePropertyName(i)); + table.addData(metadata.getColumnPropertyName(i), metadata + .isPKColumn(i), data); + } + + } + + public void processRecursiveRow(ResultSet rs) throws SQLException { + this.allTableData = new ArrayList(); + int i = 1; + DebugUtil.debugln(getClass(), debug, ""); + while (i <= metadata.getResultSetSize()) { + DebugUtil.debugln(getClass(), debug, ""); + TableData table = new TableData(metadata.getTablePropertyName(i)); + this.allTableData.add(table); + + while ( (i <= metadata.getResultSetSize()) && (metadata.isPKColumn(i))) { + Object data = getObject(rs, i); + DebugUtil.debugln(getClass(), debug, "Adding column: " + + metadata.getColumnPropertyName(i) + "\tValue: " + data + + "\tTable: " + metadata.getTablePropertyName(i)); + table.addData(metadata.getColumnPropertyName(i), true, data); + i++; + } + + while ( (i <= metadata.getResultSetSize()) && + (!metadata.isPKColumn(i))) { + Object data = getObject(rs, i); + DebugUtil.debugln(getClass(), debug, "Adding column: " + + metadata.getColumnPropertyName(i) + "\tValue: " + data + + "\tTable: " + metadata.getTablePropertyName(i)); + table.addData(metadata.getColumnPropertyName(i), false, data); + i++; + } + } + } + + /** + * @param rs + * @param metadata + * @param i + * @return + */ + private Object getObject(ResultSet rs, int i) + throws SQLException { + + Object data = rs.getObject(i); + + if (rs.wasNull()) + return null; + else + return metadata.getConverter(i).getPropertyValue(data); + } + + /** + * Returns a HashMap that holds data for the specified table + * + * @param tableName + * The name of the table + * @return HashMap + */ + public TableData getTable(String tableName) { + return (TableData) tableMap.get(tableName); + } + + /** + * Returns a HashMap that holds data for the specified table If the HashMap + * doesn't exist, it will be created. This is used internally to build the + * ResultSetRow, whereas getTable is used externally to retrieve existing + * table data. + * + * @param tableName + * The name of the table + * @return HashMap + */ + private TableData getRawData(String tableName) { + + TableData table = (TableData) tableMap.get(tableName); + + if (table == null) { + table = new TableData(tableName); + tableMap.put(tableName, table); + } + + return table; + } + + public ArrayList getAllTableData() { + if ( this.allTableData == null ) { + this.allTableData = new ArrayList(); + this.allTableData.addAll(tableMap.values()); + } + DebugUtil.debugln(getClass(), debug, allTableData); + + return this.allTableData; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/RowObjects.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/RowObjects.java new file mode 100644 index 0000000000..5c366a1898 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/RowObjects.java @@ -0,0 +1,140 @@ +/** +* +* Copyright 2005 The Apache Software Foundation or its licensors, as applicable. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.apache.tuscany.das.rdb.graphbuilder.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.tuscany.das.rdb.config.KeyPair; +import org.apache.tuscany.das.rdb.config.Relationship; +import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper; +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.DataObject; +import commonj.sdo.Property; + + +public class RowObjects { + + private HashMap objectsByTableName; + + private ArrayList tableObjects; + + private static final boolean debug = false; + + private final GraphBuilderMetadata metadata; + + private final TableRegistry registry; + + public RowObjects(GraphBuilderMetadata metadata, TableRegistry registry) { + objectsByTableName = new HashMap(); + tableObjects = new ArrayList(); + this.metadata = metadata; + this.registry = registry; + } + + public void put(String key, DataObject value) { + objectsByTableName.put(key, value); + tableObjects.add(value); + } + + public DataObject get(String tablePropertyName) { + return (DataObject) objectsByTableName.get(tablePropertyName); + } + + void processRelationships() { + MappingWrapper wrapper = new MappingWrapper(metadata.getMapping()); + if (wrapper.hasRecursiveRelationships()) { + processRecursiveRelationships(wrapper); + return; + } + + Iterator i = metadata.getRelationships().iterator(); + while (i.hasNext()) { + Relationship r = (Relationship) i.next(); + + + DataObject parentTable = get(wrapper + .getTableTypeName(r.getPrimaryKeyTable())); + DataObject childTable = get(wrapper + .getTableTypeName(r.getForeignKeyTable())); + + DebugUtil.debugln(getClass(), debug, "Parent table: " + parentTable); + DebugUtil.debugln(getClass(), debug, "Child table: " + childTable); + + if ((parentTable == null) || (childTable == null)) + continue; + + Property p = parentTable.getType().getProperty(r.getName()); + setOrAdd(parentTable, childTable, p); + + } + } + + + + private void processRecursiveRelationships(MappingWrapper wrapper) { + Iterator i = tableObjects.iterator(); + while (i.hasNext()) { + DataObject table = (DataObject) i.next(); + + Iterator relationships = wrapper.getRelationshipsByChildTable(table.getType().getName()).iterator(); + while ( relationships.hasNext() ) { + Relationship r = (Relationship) relationships.next(); + + DataObject parentTable = findParentTable(table, r, wrapper); + + if (parentTable == null) + continue; + + Property p = parentTable.getType().getProperty(r.getName()); + setOrAdd(parentTable, table, p); + } + + } + } + + private void setOrAdd(DataObject parent, DataObject child, Property p) { + if (p.isMany()) { + parent.getList(p).add(child); + } else { + parent.set(p, child); + } + } + + private DataObject findParentTable(DataObject childTable, + Relationship r, MappingWrapper wrapper) { + + ArrayList fkValue = new ArrayList(); + Iterator keyPairs = r.getKeyPair().iterator(); + while (keyPairs.hasNext()) { + KeyPair pair = (KeyPair) keyPairs.next(); + String childProperty = wrapper.getColumnPropertyName(r.getPrimaryKeyTable(), pair.getForeignKeyColumn()); + + Property p = childTable.getType().getProperty(childProperty); + fkValue.add(childTable.get(p)); + } + + DebugUtil.debugln(getClass(), debug, "Trying to find parent of " + r.getForeignKeyTable() + " with FK " + + fkValue); + DataObject parentTable = registry.get(r.getPrimaryKeyTable(), fkValue); + DebugUtil.debugln(getClass(), debug, "Parent table from registry: " + parentTable); + return parentTable; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java new file mode 100644 index 0000000000..f00ef2770d --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java @@ -0,0 +1,52 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.impl; + +import java.util.List; + +import commonj.sdo.DataObject; + +/** + */ +public class SingleTableRegistry implements TableRegistry { + + //private HashMap<List,DataObject> values = new HashMap<List,DataObject>(); + + public SingleTableRegistry() { + // Empty Constructor + } + + /* (non-Javadoc) + * @see com.ibm.ws.sdo.mediator.jdbc.graphbuilder.impl.TableRegistry#get(java.lang.String, java.util.List) + */ + public DataObject get(String tableName, List primaryKey) { + return null; + } + + /* (non-Javadoc) + * @see com.ibm.ws.sdo.mediator.jdbc.graphbuilder.impl.TableRegistry#put(java.lang.String, java.util.List, java.lang.Object) + */ + public void put(String tableName, List primaryKey, DataObject value) { + // do nothing + + } + + public boolean contains(String name, List list) { + return false; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableData.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableData.java new file mode 100644 index 0000000000..48b6dc0187 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableData.java @@ -0,0 +1,75 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + + +/** + * + */ +public class TableData { + + private HashMap columnData = new HashMap(); + private ArrayList primaryKey = new ArrayList(); + private final String name; + private boolean hasValidPrimaryKey = true; + private static final boolean debug = false; + + public TableData(String tableName) { + DebugUtil.debugln(getClass(), debug, "Creating TableData for table " + tableName); + this.name = tableName; + } + + + public void addData(String columnName, boolean isPrimaryKeyColumn, Object data) { + DebugUtil.debugln(getClass(), debug, "Adding column " + columnName + " with value " + data); + columnData.put(columnName, data); + if ( isPrimaryKeyColumn ) { + if ( data == null ) { + DebugUtil.debugln(getClass(), debug, "Column " + columnName + " is a primary key column and is null"); + hasValidPrimaryKey = false; + } + primaryKey.add(data); + } + } + + public Object getColumnData(String columnName) { + return columnData.get(columnName); + } + + public String getTableName() { + return this.name; + } + + + /** + * @return + */ + public List getPrimaryKeyValues() { + return primaryKey; + } + + + public boolean hasValidPrimaryKey() { + return hasValidPrimaryKey; + } +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java new file mode 100644 index 0000000000..4b5a3677ae --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.impl; + +import java.util.List; + +import commonj.sdo.DataObject; + +/** + */ +public interface TableRegistry { + /** + * Get the table with the specified name and primary key + * @param tableName + * @param primaryKey + * @return EDataObject + */ + public DataObject get(String tableName, List primaryKey); + + /** + * Add the table with the specified name and primary key + * @param tableName + * @param primaryKey + * @param value + */ + public void put(String tableName, List primaryKey, DataObject value); + + public boolean contains(String name, List list); +}
\ No newline at end of file diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/schema/ESchemaMaker.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/schema/ESchemaMaker.java new file mode 100644 index 0000000000..170b597134 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/schema/ESchemaMaker.java @@ -0,0 +1,203 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.schema; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.tuscany.das.rdb.config.Relationship; +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.ResultMetadata; +import org.apache.tuscany.das.rdb.util.DebugUtil; +import org.apache.tuscany.sdo.helper.TypeHelperImpl; +import org.apache.tuscany.sdo.util.DataObjectUtil; +import org.apache.tuscany.sdo.util.SDOUtil; +import org.eclipse.emf.ecore.EPackage; + +import commonj.sdo.Property; +import commonj.sdo.Type; +import commonj.sdo.helper.TypeHelper; + +/** + * + * An ESchemaMaker is used to create an EMF Schema from an instance of JDBC + * Mediator Metadata. + * + */ +public class ESchemaMaker { + + private final GraphBuilderMetadata metadata; + + private boolean debug = false; + + private TypeHelper typeHelper = SDOUtil.createTypeHelper(); + + /** + * Constructor for ESchemaMaker. Creates an SDO model based on the metadata + * passed in. + * + * @param metadata + */ + public ESchemaMaker(GraphBuilderMetadata metadata) { + this.metadata = metadata; + } + + /** + * Creates an EMF Schema by using the + * + * @link TableMaker and + * @link RelationshipMaker to transform + * @link Metadata elements into EMF Schema elements. + */ + + public Type createTypes() { + + DataObjectUtil.initRuntime(); + SDOUtil.createDataGraph(); + + + Type rootType = SDOUtil.createType(typeHelper, getURI(), "DataGraphRoot", false); + + Iterator iter = metadata.getResultMetadata().iterator(); + while (iter.hasNext()) { + + ResultMetadata resultMetadata = (ResultMetadata) iter.next(); + + // Create a Type for each Table represented in the ResultSet + Iterator names = resultMetadata.getAllTablePropertyNames() + .iterator(); + while (names.hasNext()) { + String tableName = (String) names.next(); + + Type tableType = SDOUtil.createType(typeHelper, getURI(), tableName, false); + Property property = SDOUtil.createProperty(rootType, tableName, tableType); + SDOUtil.setMany(property,true); + SDOUtil.setContainment(property, true); + } + + // TODO tablePropertyMap is temporary until Tuscany-203 is fixed + HashMap tablePropertyMap = new HashMap(); + + for (int i = 1; i <= resultMetadata.getResultSetSize(); i++) { + + Property ref = rootType.getProperty(resultMetadata.getTablePropertyName(i)); + + // TODO Temporary code to check to see if a property has already been added. + // Replace when Tuscany-203 is fixed + ArrayList addedProperties = (ArrayList) tablePropertyMap.get(ref.getName()); + if ( addedProperties == null ) { + addedProperties = new ArrayList(); + tablePropertyMap.put(ref.getName(), addedProperties); + } + + if (ref == null) + throw new RuntimeException("Could not find table " + + resultMetadata.getTablePropertyName(i) + + " in the SDO model"); + + String columnName = resultMetadata.getColumnPropertyName(i); + + // TODO temporary check until Tuscany-203 is fixed + if ( !addedProperties.contains(columnName)) { + addedProperties.add(columnName); + Type atype = resultMetadata.getDataType(i); + + SDOUtil.createProperty(ref.getType(), columnName, atype); + + DebugUtil.debugln(getClass(), debug, "Adding column " + + columnName + " to " + + resultMetadata.getTablePropertyName(i)); + } + + } + } + + if (metadata.hasMappingModel()) { + MappingWrapper wrapper = new MappingWrapper(metadata.getMapping()); + Iterator i = metadata.getRelationships().iterator(); + while (i.hasNext()) { + Relationship r = (Relationship) i.next(); + + String parentName = wrapper.getTableTypeName(r.getPrimaryKeyTable()); + String childName = wrapper.getTableTypeName(r.getForeignKeyTable()); + + if (parentName == null) { + throw new RuntimeException("The parent table (" + + r.getPrimaryKeyTable() + ") in relationship " + + r.getName() + + " was not found in the mapping information."); + } else if (childName == null) { + throw new RuntimeException("The child table (" + + r.getForeignKeyTable() + ") in relationship " + + r.getName() + + " was not found in the mapping information."); + } + + Property parentProperty = rootType.getProperty(parentName); + Property childProperty = rootType.getProperty(childName); + + if (parentProperty == null) { + throw new RuntimeException("The parent table (" + + parentName + ") in relationship " + + r.getName() + + " was not found."); + } else if (childProperty == null) { + throw new RuntimeException("The child table (" + + childName + ") in relationship " + + r.getName() + + " was not found."); + } + + Type parent = parentProperty.getType(); + Type child = childProperty.getType(); + + Property parentProp = SDOUtil.createProperty(parent, r.getName(), child); + Property childProp = SDOUtil.createProperty(child, r.getName() + "_opposite", parent); + SDOUtil.setOpposite(parentProp, childProp); + SDOUtil.setOpposite(childProp, parentProp); + SDOUtil.setMany(parentProp, r.isMany()); + } + + } + + return rootType; + } + + private String getURI() { + return "http:///org.apache.tuscany.das.rdb/das"; + } + + public Type createTypes(String uri) { + Type rootType = SDOUtil.createType(typeHelper, getURI() + "/DataGraphRoot", "DataGraphRoot", false); + + EPackage pkg = ((TypeHelperImpl)typeHelper).getExtendedMetaData().getPackage(uri); + if ( pkg == null ) + throw new RuntimeException("SDO Types have not been registered for URI " + uri); + Iterator i = pkg.getEClassifiers().iterator(); + while ( i.hasNext() ) { + Type type = (Type) i.next(); + Property property = SDOUtil.createProperty(rootType, type.getName(), type); + SDOUtil.setContainment(property, true); + SDOUtil.setMany(property, true); + } + return rootType; + } + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/schema/ResultSetTypeMap.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/schema/ResultSetTypeMap.java new file mode 100644 index 0000000000..832cfeac7e --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/schema/ResultSetTypeMap.java @@ -0,0 +1,133 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.graphbuilder.schema; + +import java.sql.Types; + +import org.apache.tuscany.sdo.SDOPackage; + +import commonj.sdo.Type; +import commonj.sdo.helper.TypeHelper; + +/** + */ +public class ResultSetTypeMap { + + public static ResultSetTypeMap instance = new ResultSetTypeMap(); + + /** + * Constructor for ResultSetTypeMap. + */ + protected ResultSetTypeMap() { + // Empty Constructor + } + + /** + * These mappings taken primarily from "JDBC API and Tutorial and Reference" by + * Fisher, Ellis and Bruce. + * + * @param type + * @param isNullable + * @return + */ + public Type getEDataType(int type, boolean isNullable) { + + TypeHelper helper = TypeHelper.INSTANCE; + SDOPackage.eINSTANCE.eClass(); + switch (type) { + + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + return helper.getType("commonj.sdo", "String"); + + case Types.NUMERIC: + case Types.DECIMAL: + return helper.getType("commonj.sdo", "Decimal"); + + case Types.BIT: + case Types.BOOLEAN: + if (isNullable) + return helper.getType("commonj.sdo", "Boolean"); + else + return helper.getType("commonj.sdo", "boolean"); + + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + if (isNullable) { + return helper.getType("commonj.sdo", "IntObject"); + } else + return helper.getType("commonj.sdo", "Int"); + + case Types.BIGINT: + if (isNullable) + return helper.getType("commonj.sdo", "Long"); + else + return helper.getType("commonj.sdo", "long"); + + case Types.REAL: + if (isNullable) + return helper.getType("commonj.sdo", "Float"); + else + return helper.getType("commonj.sdo", "float"); + + case Types.FLOAT: + case Types.DOUBLE: + if (isNullable) + return helper.getType("commonj.sdo", "Double"); + else + return helper.getType("commonj.sdo", "double"); + + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + return helper.getType("commonj.sdo", "ByteArray"); + + case Types.DATE: + case Types.TIME: + case Types.TIMESTAMP: + return helper.getType("commonj.sdo", "Date"); + + case Types.CLOB: + return helper.getType("commonj.sdo", "Clob"); + + case Types.BLOB: + return helper.getType("commonj.sdo", "Blob"); + + case Types.ARRAY: + return helper.getType("commonj.sdo", "Array"); + + case Types.DISTINCT: + case Types.STRUCT: + case Types.REF: + case Types.DATALINK: + case Types.JAVA_OBJECT: + return helper.getType("commonj.sdo", "Object"); + + default: + return helper.getType("commonj.sdo", "Object"); + } + + } + + + public Type getType(int columnType, boolean b) { + return getEDataType(columnType, b); + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java new file mode 100644 index 0000000000..610adf3ff6 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ApplyChangesCommandImpl.java @@ -0,0 +1,93 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.sql.Connection; + +import org.apache.tuscany.das.rdb.Command; +import org.apache.tuscany.das.rdb.config.Config; +import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper; +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.DataObject; +import commonj.sdo.Type; + +/** + * + */ +public class ApplyChangesCommandImpl extends BaseCommandImpl { + + private static final boolean debug = false; + + private ChangeSummarizer summarizer = new ChangeSummarizer(); + + public ApplyChangesCommandImpl() { + } + + public ApplyChangesCommandImpl(Config config){ + this.configWrapper = new MappingWrapper(config); + } + + public ApplyChangesCommandImpl(Config config, Connection connection){ + this.configWrapper = new MappingWrapper(config); + if ( connection != null ) + setConnection(connection, config); + + } + + public void setConnection(ConnectionImpl connection) { + summarizer.setConnection(connection); + } + + public void addCreateCommand(Type type, Command cmd) { + summarizer.addCreateCommand(type, cmd); + } + + public void addUpdateCommand(Type type, Command cmd) { + summarizer.addUpdateCommand(type, cmd); + } + + public void addDeleteCommand(Type type, Command cmd) { + summarizer.addDeleteCommand(type, cmd); + } + + public void execute(DataObject root) { + DebugUtil.debugln(getClass(), 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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java new file mode 100644 index 0000000000..1b9ac360e5 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/BaseCommandImpl.java @@ -0,0 +1,48 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java new file mode 100644 index 0000000000..24fca8fe10 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java @@ -0,0 +1,183 @@ +/** +* +* Copyright 2005 The Apache Software Foundation or its licensors, as applicable. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.apache.tuscany.das.rdb.impl; + +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 org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.DataObject; +import commonj.sdo.Type; + +public class ChangeFactory { + + private final Type type; + + private InsertCommandImpl createCommand; + + private UpdateCommandImpl updateCommand; + + private DeleteCommandImpl deleteCommand; + + private static final boolean debug = false; + + private final MappingWrapper mapping; + + private final ConnectionImpl connection; + + public ChangeFactory(Type type, MappingWrapper mapping, ConnectionImpl connection) { + this.type = type; + this.mapping = mapping; + this.connection = connection; + } + + public Type getType() { + return this.type; + } + + public void setCreateCommand(InsertCommandImpl cmd) { + createCommand = cmd; + } + + public void setUpdateCommand(UpdateCommandImpl cmd) { + DebugUtil.debugln(getClass(), 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); + } + + ChangeOperation createInsertOperation(DataObject changedObject) { + return createInsertOperation(changedObject, null); + } + + + 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(table); + } else { + deleteCommand = new DeleteCommandImpl(delete); + } + deleteCommand.setConnection(connection); + } + return deleteCommand; + } + + private UpdateCommandImpl getUpdateCommand(DataObject changedObject) { + + if ( updateCommand == 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"); + } + } + + 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; + } + DebugUtil.debugln(getClass(), debug, "Returning updateCommand: " + updateCommand); + return updateCommand; + } + + public MappingWrapper getConfig() { + return this.mapping; + } + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java new file mode 100644 index 0000000000..5db52bf2be --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeOperation.java @@ -0,0 +1,78 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.util.Iterator; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.DataObject; + +/** + */ +public abstract class ChangeOperation { + + private final WriteCommandImpl writeCommand; + + protected DatabaseObject dObject; + + private static final boolean debug = false; + + protected String propagatedID = null; + + private boolean isInsert = false; + + 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() { + DebugUtil.debugln(getClass(), debug, "Executing change operation"); + + Iterator i = writeCommand.getParameters().iterator(); + while (i.hasNext()) { + ParameterImpl parm = (ParameterImpl) i.next(); + DebugUtil.debugln(getClass(), debug, "setting " + parm.getName() + " to " + dObject.get(parm.getName())); + parm.setValue(dObject.get(parm.getName())); + } + + writeCommand.execute(); + + if ( isInsert && ( propagatedID != null )) { + DebugUtil.debugln(getClass(), debug, "Propagating key " + propagatedID); + int id = writeCommand.getGeneratedKey(); + dObject.setPropagatedID(propagatedID, id); + } + } + + public String getTableName() { + return dObject.getTableName(); + } + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java new file mode 100644 index 0000000000..78addfb72c --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ChangeSummarizer.java @@ -0,0 +1,239 @@ +/** +* +* Copyright 2005 The Apache Software Foundation or its licensors, as applicable. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.apache.tuscany.das.rdb.impl; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.apache.tuscany.das.rdb.Command; +import org.apache.tuscany.das.rdb.config.Column; +import org.apache.tuscany.das.rdb.config.Relationship; +import org.apache.tuscany.das.rdb.config.Table; +import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper; +import org.apache.tuscany.das.rdb.config.wrapper.RelationshipWrapper; +import org.apache.tuscany.das.rdb.config.wrapper.TableWrapper; +import org.apache.tuscany.das.rdb.util.DebugUtil; +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 static final boolean debug = false; + + private Changes changes = new Changes(); + + private FactoryRegistry registry; + + private MappingWrapper mapping = new MappingWrapper(); + + private ConnectionImpl connection; + + private HashMap 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(); + DebugUtil.debugln(getClass(), 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)) { + DebugUtil.debugln(getClass(), 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()); + DebugUtil.debugln(getClass(), debug, "Change is a delete"); + changes.addDelete(factory.createDeleteOperation(changedObject)); + } else { + // bumpCollisionField(changedObject); + DebugUtil.debugln(getClass(), debug, "Change is a modify"); + List attrList = changeSummary.getOldValues(changedObject); + if (hasAttributeChange(attrList)) { + ChangeFactory factory = getRegistry().getFactory( + changedObject.getType()); + DebugUtil.debugln(getClass(), debug, "Attribute Change for " + + changedObject.getType().getName()); + String propagatedID = (String) generatedKeys.get(changedObject + .getType().getName()); + changes.addUpdate(factory.createUpdateOperation(changedObject, + propagatedID)); + } else { + // Reference change + List values = changeSummary.getOldValues(changedObject); + Iterator i = values.iterator(); + while (i.hasNext()) { + ChangeSummary.Setting setting = (ChangeSummary.Setting) i + .next(); + + if (!setting.getProperty().getType().isDataType()) { + DebugUtil.debugln(getClass(), debug, + "Reference change for " + + changedObject.getType().getName()); + + Property ref = setting.getProperty(); + + DebugUtil.debugln(getClass(), 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; + } else { + 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()) { + // 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()) { + DebugUtil.debugln(getClass(), debug, "adding generated key " + + t.getTableName() + "." + + c.getColumnName()); + generatedKeys.put(t.getTableName(), c.getColumnName()); + } + } + } + } + + + public ConnectionImpl getConnection() { + return this.connection; + } + + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java new file mode 100644 index 0000000000..77198fe589 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Changes.java @@ -0,0 +1,80 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.util.ArrayList; +import java.util.Iterator; + +/** + * Mangages 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(ArrayList insertOrder) { + inserts.setOrder(insertOrder); + } + + public void setDeleteOrder(ArrayList deleteOrder) { + deletes.setOrder(deleteOrder); + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java new file mode 100644 index 0000000000..0a2cc7a5f1 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CommandImpl.java @@ -0,0 +1,100 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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 static final boolean debug = false; + + 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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java new file mode 100644 index 0000000000..d6ef150d6d --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ConnectionImpl.java @@ -0,0 +1,95 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.sql.CallableStatement; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + + +public class ConnectionImpl { + + private Connection connection; + private static final boolean debug = false; + + private boolean managingTransaction = true; + + public ConnectionImpl(Connection connection) { + this.connection = connection; + + try { + if (connection.getAutoCommit()) + throw new RuntimeException("AutoCommit must be off!"); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + } + + public Connection getJDBCConnection() { + return connection; + } + + public void cleanUp() { + try { + if (managingTransaction) { + DebugUtil.debugln(getClass(), debug, "Committing Transaction"); + connection.commit(); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public void errorCleanUp() { + try { + if (managingTransaction) { + DebugUtil.debugln(getClass(), debug, "Rolling back Transaction"); + connection.rollback(); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public PreparedStatement prepareStatement(String queryString) + throws SQLException { + DebugUtil.debugln(getClass(), debug, "Preparing Statement: " + queryString); + return connection.prepareStatement(queryString, java.sql.Statement.RETURN_GENERATED_KEYS); + } + + public PreparedStatement preparePagedStatement(String queryString) throws SQLException { + DebugUtil.debugln(getClass(), debug, "Preparing Statement: " + queryString); + return connection.prepareStatement(queryString, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + } + + public void setManageTransactions(boolean manageTransactions) { + managingTransaction = manageTransactions; + + } + + public CallableStatement prepareCall(String queryString) throws SQLException { + return connection.prepareCall(queryString); + } + + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java new file mode 100644 index 0000000000..5c70dc1e6f --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/CreateOperation.java @@ -0,0 +1,29 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java new file mode 100644 index 0000000000..dded0aa46e --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASFactoryImpl.java @@ -0,0 +1,53 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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() { + return new DASImpl(); + } + + 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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java new file mode 100644 index 0000000000..ee38c04faa --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DASImpl.java @@ -0,0 +1,234 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.io.InputStream; +import java.sql.Connection; +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.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 Config config; + + private Connection connection; + + private Map commands = new HashMap(); + + public DASImpl(InputStream stream) { + this(ConfigUtil.loadConfig(stream)); + + } + + public DASImpl(Config inConfig) { + this.config = inConfig; + + Iterator i = config.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(), config, 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())); + 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(),config, commandConfig.getParameter())); + else + throw new RuntimeException("Invalid kind of command: " + kind); + + } + + } + + public DASImpl() { + // Empty Constructor + } + + 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) { + setConnection(inConnection); + } + + /* + * (non-Javadoc) + * + * @see org.apache.tuscany.das.rdb.CommandGroup#getApplyChangesCommand() + */ + public ApplyChangesCommandImpl getApplyChangesCommand() { + ApplyChangesCommandImpl cmd = new ApplyChangesCommandImpl(config, 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(), config); + return cmd; + } + + + public void setConnection(Connection connection) { + this.connection = connection; + } + + public Connection getConnection() { + if (connection == null) + initializeConnection(); + return connection; + } + + private void initializeConnection() { + + if (config == null || + config.getConnectionInfo() == null || + config.getConnectionInfo().getDataSource() == null) + throw new RuntimeException( + "No connection has been provided and no data source has been specified"); + + Connection connection = null; + + InitialContext ctx; + try { + ctx = new InitialContext(); + } catch (NamingException e) { + throw new RuntimeException(e); + } + try { + // TODO - I think we should rename this getDataSourceURL? + DataSource ds = (DataSource) ctx.lookup(config.getConnectionInfo().getDataSource()); + try { + connection = ds.getConnection(); + connection.setAutoCommit(false); + setConnection(connection); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } catch (NamingException e) { + throw new RuntimeException(e); + } + + } + + 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 (config.getConnectionInfo().getDataSource() == null) + return false; + else + return true; + + } + + public Command createCommand(String sql) { + return baseCreateCommand(sql, this.config); + } + + public Command createCommand(String sql, Config config) { + return baseCreateCommand(sql, config); + } + + private Command baseCreateCommand(String sql, Config config) { + CommandImpl returnCmd = null; + sql = sql.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); + 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); + return returnCmd; + } + + public void applyChanges(DataObject root) { + getApplyChangesCommand().execute(root); + } + +}
\ No newline at end of file diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java new file mode 100644 index 0000000000..e49ece3050 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DatabaseObject.java @@ -0,0 +1,148 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +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.util.DebugUtil; + +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 MappingWrapper mappingWrapper; + + private final DataObject dataObject; + + private Property parentReference; + + private static final boolean debug = false; + + private HashMap 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(); + DebugUtil.debugln(getClass(), debug, "Initializing relationship: " + r.getName()); + 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); + } + } + } + } + } + + 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); + + Property parentRef = getParentReference(r.getPrimaryKeyTable()); + 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; + } + + public String getTableName() { + if (mappingWrapper.getConfig() != null) + return mappingWrapper.getTableByTypeName(getTypeName()).getTableName(); + else + return null; + } + + public String getTypeName() { + 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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java new file mode 100644 index 0000000000..8c39dcac87 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteCommandImpl.java @@ -0,0 +1,32 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java new file mode 100644 index 0000000000..8650c6119c --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteList.java @@ -0,0 +1,72 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; + +/** + * DeleteList will sort delete operations so that child objects are deleted + * before their parents + * + * + */ +public class DeleteList { + + private HashMap opsByTableName = new HashMap(); + + private ArrayList order; + + private ArrayList deleteOperations = new ArrayList(); + + public DeleteList() { + super(); + } + + public void add(ChangeOperation op) { + if (( order == null ) || ( op.getTableName() == null ) ) { + deleteOperations.add(op); + } else { + String name = op.getTableName(); + ArrayList ops = (ArrayList) opsByTableName.get(name); + if (ops == null) + ops = new ArrayList(); + + ops.add(op); + opsByTableName.put(name, ops); + } + } + + public Collection getSortedList() { + if (( order != null ) && ( opsByTableName.keySet().size() > 0) ) { + Iterator i = this.order.iterator(); + while (i.hasNext()) { + String name = (String) i.next(); + deleteOperations.addAll((Collection) opsByTableName.get(name)); + } + } + + return deleteOperations; + } + + public void setOrder(ArrayList deleteOrder) { + this.order = deleteOrder; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java new file mode 100644 index 0000000000..7b71e0ace9 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/DeleteOperation.java @@ -0,0 +1,38 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java new file mode 100644 index 0000000000..ce09c748f4 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/FactoryRegistry.java @@ -0,0 +1,49 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.util.HashMap; + +import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper; +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.Type; + +public class FactoryRegistry { + + private HashMap registry = new HashMap(); + private static final boolean debug = false; + 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 ) { + DebugUtil.debugln(getClass(), debug, "Creating new ChangeFactory for type " + type.getName()); + factory = new ChangeFactory(type, mapping, connection); + registry.put(type, factory); + } + return factory; + } + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java new file mode 100644 index 0000000000..59e88c2f6c --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertCommandImpl.java @@ -0,0 +1,75 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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 int generatedKey; + + private boolean hasGeneratedKey = false; + + public InsertCommandImpl(String sqlString) { + super(sqlString); + } + + public InsertCommandImpl(Create create) { + super(create.getSql()); + addParameters(create.getParameters()); + } + + protected boolean isInsert() { + return true; + } + + public int getGeneratedKey() { + + if (hasGeneratedKey) + return generatedKey; + + throw new RuntimeException("No generated key is available"); + } + + protected void subtypeProcessing() throws SQLException { + loadGeneratedKey(); + } + + private void loadGeneratedKey() throws SQLException { + Integer key = statement.getGeneratedKey(); + if (key != null) { + hasGeneratedKey = true; + generatedKey = key.intValue(); + } + + } + + public String toString() { + + String superString = super.toString(); + StringBuffer buffer = new StringBuffer(superString); + + buffer.append("\nGenerating key: " + hasGeneratedKey); + if (hasGeneratedKey) + buffer.append("\nGenerated key: " + generatedKey); + + return buffer.toString(); + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java new file mode 100644 index 0000000000..dee6546cfe --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/InsertList.java @@ -0,0 +1,82 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + +/** + * InsertList will sort ChangeOperation objects so that parents are inserted + * before children + * + * + */ +public class InsertList { + + private HashMap opsByTableName = new HashMap(); + + private ArrayList insertOperations = new ArrayList(); + + private ArrayList order; + + private static final boolean debug = false; + + public void add(ChangeOperation op) { + DebugUtil.debugln(getClass(), 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(); + ArrayList ops = (ArrayList) opsByTableName.get(name); + if (ops == null) + ops = new ArrayList(); + + ops.add(op); + opsByTableName.put(name, ops); + } + } + + public Collection getSortedList() { + DebugUtil.debugln(getClass(), 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(); + DebugUtil.debugln(getClass(), 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)); + } + } + DebugUtil.debugln(getClass(), debug, "Returning " + + insertOperations.size() + " insert operations"); + return insertOperations; + } + + public void setOrder(ArrayList insertOrder) { + this.order = insertOrder; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java new file mode 100644 index 0000000000..96a064b8e4 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ManagedParameterImpl.java @@ -0,0 +1,17 @@ +package org.apache.tuscany.das.rdb.impl; + +public class ManagedParameterImpl extends ParameterImpl { + + public void setValue(Object oldValue) { + this.value = updateValue(oldValue); + } + + private Object updateValue(Object oldValue) { + if ( oldValue instanceof Integer) + return new Integer( ((Integer)oldValue).intValue() + 1); + else + throw new RuntimeException("Unsupported type for managed column: " + oldValue.getClass().getName()); + } + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java new file mode 100644 index 0000000000..666e1186b5 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/OptimisticWriteCommandImpl.java @@ -0,0 +1,52 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.sql.SQLException; + +import org.apache.tuscany.das.rdb.config.Update; + +public class OptimisticWriteCommandImpl extends UpdateCommandImpl { + + public OptimisticWriteCommandImpl(String sqlString) { + super(sqlString); + } + + public OptimisticWriteCommandImpl(Update update) { + super(update); + addParameters(update.getParameters()); + } + + public void execute() { + + boolean success = false; + try { + int rowsAffected = statement.executeUpdate(parameters); + success = true; + if ( rowsAffected == 0 ) + throw new RuntimeException("OCC Exception"); + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + if (success) + statement.getConnection().cleanUp(); + else + statement.getConnection().errorCleanUp(); + } + + } +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java new file mode 100644 index 0000000000..32b17ef3e7 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/PagerImpl.java @@ -0,0 +1,64 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java new file mode 100644 index 0000000000..f5c5d01375 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ParameterImpl.java @@ -0,0 +1,126 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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. + */ + final static int IN = 1; + + /** + * Value for "Direction" that indicates that a parameter is soley for + * output. Out parameters only apply to Stored Procedures + */ + final static 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 + */ + final static int IN_OUT = 3; + + private int index; + private Type type; + private String name; + protected Object value = null; + private int direction = IN; + private Converter converter; + + public ParameterImpl() { + super(); + } + + public ParameterImpl(String name) { + this.name = name; + } + + 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); + } else { + return this.value; + } + } + + public int getDirection() { + return this.direction; + } + + public void setConverter(Converter converter) { + this.converter = converter; + } + + public Converter getConverter() { + return this.converter; + } + + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("Index: " + getIndex()); + buffer.append("\nName: " + getName()); + buffer.append("\nValue: " + getValue()); + return buffer.toString(); + } + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java new file mode 100644 index 0000000000..506d7285fe --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Parameters.java @@ -0,0 +1,110 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.Type; + +public class Parameters { + + private ArrayList parameters = new ArrayList(); + + private ArrayList inParams = new ArrayList(); + + private ArrayList outParams = new ArrayList(); + + private static boolean debug = false; + + 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; + } + DebugUtil.debugln(getClass(), 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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/QueryString.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/QueryString.java new file mode 100644 index 0000000000..d8a26057d1 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/QueryString.java @@ -0,0 +1,86 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + + +public class QueryString { + + private final String unmodifiedQueryString; + private final String preparedString; + private HashMap parameters = new HashMap(); + private static final boolean debug = false; + + public QueryString(String originalString) { + this.unmodifiedQueryString = originalString; + this.preparedString = replaceNamesAndSetIndexes(originalString); + } + + public String getPreparedString() { + return this.preparedString; + } + + public String getUnmodifiedString() { + return this.unmodifiedQueryString; + } + + public int getParameterIndex(String name) { + DebugUtil.debugln(getClass(), debug, "Looking for parameter index for: " + name); + return ((Integer)parameters.get(name)).intValue(); + } + + private String replaceNamesAndSetIndexes(String query) { + DebugUtil.debugln(getClass(), debug, "Parameterizing query: " + query); + Pattern p = Pattern.compile(":[\\S&&[^,()]]*"); + Matcher m = p.matcher(query); + + int index = 1; + while (m.find()) { + parameters.put(m.group().substring(1), new Integer(index)); + query = m.replaceFirst("?"); + m = p.matcher(query); + index++; + } + + DebugUtil.debugln(getClass(), debug, "Parameterized query: " + query); + return query; + } + + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("\nOriginal SQL: "); + buffer.append(unmodifiedQueryString); + buffer.append("\nPrepared SQL: "); + buffer.append(preparedString); + buffer.append("\nParameters: "); + Iterator i = parameters.keySet().iterator(); + while ( i.hasNext() ) { + String key = (String)i.next(); + buffer.append("\n"); + buffer.append(key); + } + return buffer.toString(); + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java new file mode 100644 index 0000000000..d70f1e5693 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ReadCommandImpl.java @@ -0,0 +1,127 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.das.rdb.config.Config; +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, Config mapping, List resultDescriptor) { + super(sqlString); + if (mapping != null) + setMappingModel(mapping); + + if ( resultDescriptor != null && !resultDescriptor.isEmpty()) + this.resultSetShape = new ResultSetShape(resultDescriptor); + } + + + 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 { + ResultSet rs = statement.executeQuery(parameters); + success = true; + return buildGraph(rs); + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + if (success) + statement.getConnection().cleanUp(); + else + statement.getConnection().errorCleanUp(); + } + } + + protected DataObject buildGraph(ResultSet result) throws SQLException { + + List results = new ArrayList(); + results.add(result); + + // 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.getSchema()); + + 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; + } + + private void setMappingModel(Config config) { + configWrapper = new MappingWrapper(config); + } + + protected void enablePaging() { + statement.enablePaging(); + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java new file mode 100644 index 0000000000..2f1567c1cf --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/ResultSetShape.java @@ -0,0 +1,118 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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.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; + + public ResultSetShape(ResultSetMetaData metadata) throws SQLException { + columns = new String[metadata.getColumnCount()]; + tables = new String[metadata.getColumnCount()]; + types = new Type[metadata.getColumnCount()]; + + ResultSetTypeMap typeMap = ResultSetTypeMap.instance; + for (int i = 1; i <= metadata.getColumnCount(); i++) { + tables[i-1] = metadata.getTableName(i); + columns[i-1] = metadata.getColumnName(i); + types[i-1] = typeMap.getType(metadata.getColumnType(i), true); + } + } + + public ResultSetShape(List resultDescriptor) { + TypeHelper helper = TypeHelper.INSTANCE; + int size = resultDescriptor.size(); + columns = new String[size]; + tables = new String[size]; + types = new Type[size]; + + for (int i=0; i<size; i++) { + ResultDescriptor desc = (ResultDescriptor) resultDescriptor.get(i); + tables[i] = desc.getTableName(); + 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]; + } + + 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/type: "); + for (int i=0; i < columns.length; i++) { + result.append(columns[i]); + result.append('\t'); + result.append(tables[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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java new file mode 100644 index 0000000000..49a06a358d --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypeHelper.java @@ -0,0 +1,102 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.sql.Types; + + +import commonj.sdo.Type; + +public class SDODataTypeHelper { + + static public 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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java new file mode 100644 index 0000000000..1a9e2143ff --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SDODataTypes.java @@ -0,0 +1,64 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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 { + + static TypeHelper helper = TypeHelper.INSTANCE; + + final public static Type BOOLEAN = helper.getType("commonj.sdo", "Boolean"); + final public static Type BYTE = helper.getType("commonj.sdo", "Byte"); + final public static Type BYTES = helper.getType("commonj.sdo", "Bytes"); + final public static Type CHARACTER = helper.getType("commonj.sdo", "Character"); + final public static Type DATE = helper.getType("commonj.sdo", "Date"); + final public static Type DATETIME = helper.getType("commonj.sdo", "Date"); + final public static Type DAY = helper.getType("commonj.sdo", "Date"); + final public static Type DECIMAL = helper.getType("commonj.sdo", "Float"); + final public static Type DOUBLE =helper.getType("commonj.sdo", "Double"); + final public static Type DURATION = helper.getType("commonj.sdo", "Date"); + final public static Type FLOAT = helper.getType("commonj.sdo", "Float"); + final public static Type INT = helper.getType("commonj.sdo", "Int"); + final public static Type INTEGER = helper.getType("commonj.sdo", "Integer"); + final public static Type LONG = helper.getType("commonj.sdo", "Long"); + final public static Type MONTH = helper.getType("commonj.sdo", "Date"); + final public static Type MONTHDAY = helper.getType("commonj.sdo", "Date"); + final public static Type OBJECT = helper.getType("commonj.sdo", "Object"); + final public static Type SHORT = helper.getType("commonj.sdo", "Short"); + final public static Type STRING = helper.getType("commonj.sdo", "String"); + final public static Type STRINGS = helper.getType("commonj.sdo", "String"); + final public static Type TIME = helper.getType("commonj.sdo", "Date"); + final public static Type URI = helper.getType("commonj.sdo", "String"); + final public static Type YEAR = helper.getType("commonj.sdo", "Date"); + final public static Type YEARMONTH = helper.getType("commonj.sdo", "Date"); + final public static Type YEARMONTHDAY = helper.getType("commonj.sdo", "Date"); + final public static Type BOOLEANOBJECT = helper.getType("commonj.sdo", "BooleanObject"); + final public static Type BYTEOBJECT = helper.getType("commonj.sdo", "ByteObject"); + final public static Type CHARACTEROBJECT = helper.getType("commonj.sdo", "CharacterObject"); + final public static Type DOUBLEOBJECT = helper.getType("commonj.sdo", "DoubleObject"); + final public static Type FLOATOBJECT = helper.getType("commonj.sdo", "FloatObject"); + final public static Type INTEGEROBJECT = helper.getType("commonj.sdo", "IntObject"); + final public static Type LONGOBJECT = helper.getType("commonj.sdo", "LongObject"); + final public static Type SHORTOBJECT = helper.getType("commonj.sdo", "ShortObject"); + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java new file mode 100644 index 0000000000..999cd0f267 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/SPCommandImpl.java @@ -0,0 +1,93 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.List; + +import org.apache.tuscany.das.rdb.config.Config; +import org.apache.tuscany.das.rdb.config.Parameter; +import org.apache.tuscany.das.rdb.util.DebugUtil; + +import commonj.sdo.DataObject; +import commonj.sdo.Type; +import commonj.sdo.helper.TypeHelper; + +public class SPCommandImpl extends ReadCommandImpl { + + public SPCommandImpl(String sqlString, Config config, List params) { + super(sqlString, config, null); + Iterator i = params.iterator(); + for (int idx = 1; i.hasNext(); idx++) { + 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(idx, direction, sdoType); + } + + } + + public DataObject executeQuery() { + + boolean success = false; + try { + ResultSet rs = statement.executeCall(parameters); + success = true; + + return buildGraph(rs); + } catch (SQLException e) { + DebugUtil.debugln(getClass(), 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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java new file mode 100644 index 0000000000..f40f04489a --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/Statement.java @@ -0,0 +1,210 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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.Iterator; + +import org.apache.tuscany.das.rdb.util.DebugUtil; + +// TODO - Can use some refactoring. Much code is duplicated in "execute" methods +public class Statement { + + protected final String queryString; + + protected ConnectionImpl jdbcConnection; + + private static final boolean debug = false; + + private PreparedStatement preparedStatement; + + private boolean isPaging = false; + + public Statement(String sqlString) { + this.queryString = sqlString; //new QueryString(sqlString); + } + + public ResultSet executeQuery(Parameters parameters) throws SQLException { + + PreparedStatement ps = getPreparedStatement(); + ps = setParameters(ps, parameters); + ResultSet rs = ps.executeQuery(); + + return rs; + } + + public ResultSet executeCall(Parameters parameters) throws SQLException { + try { + CallableStatement cs = jdbcConnection.prepareCall(queryString); + + Iterator inParams = parameters.inParams().iterator(); + while (inParams.hasNext()) { + ParameterImpl param = (ParameterImpl) inParams.next(); +// if (param.getIndex() == 0) +// param.setIndex(queryString.getParameterIndex(param.getName())); + cs.setObject(param.getIndex(), param.getValue()); + } + + // register out parameters + Iterator outParams = parameters.outParams().iterator(); + while (outParams.hasNext()) { + ParameterImpl param = (ParameterImpl) outParams.next(); +// if (param.getIndex() == 0) +// param.setIndex(queryString.getParameterIndex(param.getName())); + DebugUtil.debugln(getClass(), 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(); + ResultSet results = cs.getResultSet(); + + Iterator i = parameters.outParams().iterator(); + while (i.hasNext()) { + ParameterImpl param = (ParameterImpl) i.next(); + param.setValue(cs.getObject(param.getIndex())); + } + + return results; + } catch (SQLException ex) { + ex.printStackTrace(); + throw ex; + } + + } + + 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(); +// if (param.getIndex() == 0) +// param.setIndex(queryString.getParameterIndex(param.getName())); + cs.setObject(param.getIndex(), param.getValue()); + } + + // register out parameters + Iterator outParams = parameters.outParams().iterator(); + while (outParams.hasNext()) { + ParameterImpl param = (ParameterImpl) outParams.next(); +// if (param.getIndex() == 0) +// param.setIndex(queryString.getParameterIndex(param.getName())); + DebugUtil.debugln(getClass(), 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())); + } + + } + + /** + * TODO - We need to look at using specific ps.setXXX methods when a type + * has been specified and try setObject otherwise. + */ + public int executeUpdate(Parameters parameters) throws SQLException { + DebugUtil.debugln(getClass(), debug, "Executing statement " + queryString); + PreparedStatement ps = getPreparedStatement(); + Iterator i = parameters.inParams().iterator(); + while (i.hasNext()) { + ParameterImpl param = (ParameterImpl) i.next(); + +// if (param.getIndex() == 0) +// param.setIndex(queryString.getParameterIndex(param.getName())); + Object value = param.getValue(); + DebugUtil.debugln(getClass(), debug, "Setting parameter " + param.getIndex() + " to " + value); + if (value == null) { + if (param.getType() == null) { + ParameterMetaData pmd = ps.getParameterMetaData(); + ps.setNull(param.getIndex(), pmd.getParameterType(param.getIndex())); + } 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(); +// if (param.getIndex() == 0) +// param.setIndex(queryString.getParameterIndex(param.getName())); + 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() throws SQLException { + DebugUtil.debugln(getClass(), debug, "Getting prepared statement"); + if (preparedStatement == null) + if (isPaging) + preparedStatement = jdbcConnection.preparePagedStatement(queryString); + else + preparedStatement = jdbcConnection.prepareStatement(queryString); + + return preparedStatement; + } + + public Integer getGeneratedKey() throws SQLException { + + ResultSet rs = getPreparedStatement().getGeneratedKeys(); + if (rs.next()) + return new Integer(rs.getInt(1)); + + return null; + } + + protected void enablePaging() { + isPaging = true; + } + + public void close() { + + if (this.preparedStatement != null) { + try { + preparedStatement.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java new file mode 100644 index 0000000000..963cb4d847 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateCommandImpl.java @@ -0,0 +1,32 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java new file mode 100644 index 0000000000..1ab2f16fca --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateList.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.impl; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * Updates don't have to be sorted, so this class is a simple wrapper of ArrayList. + * + */ +public class UpdateList { + + private ArrayList updates = new ArrayList(); + + public UpdateList() { + super(); + } + + public void add(ChangeOperation c) { + updates .add(c); + } + + public Collection getSortedList() { + return updates; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java new file mode 100644 index 0000000000..cbe73a16e4 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/UpdateOperation.java @@ -0,0 +1,30 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java new file mode 100644 index 0000000000..386af87141 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/impl/WriteCommandImpl.java @@ -0,0 +1,101 @@ +/** +* +* Copyright 2005 The Apache Software Foundation or its licensors, as applicable. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.apache.tuscany.das.rdb.impl; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.Iterator; +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 { + statement.executeUpdate(parameters); + subtypeProcessing(); + success = true; + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + if (success) + statement.getConnection().cleanUp(); + else + statement.getConnection().errorCleanUp(); + } + + } + + public DataObject executeQuery() { + throw new UnsupportedOperationException(); + } + + public Config getMappingModel() { + return configWrapper.getConfig(); + } + + + /** + * Subclasses add specific bahavior + * Default is to do nothing + */ + protected void subtypeProcessing() throws SQLException { + if ( false ) + throw new SQLException(); + } + + 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); + } + } + public void addParameters(Collection updateParameters) { + Iterator i = updateParameters.iterator(); + while ( i.hasNext()) { + ParameterImpl p = (ParameterImpl) i.next(); + addParameter(p); + } + } + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java new file mode 100644 index 0000000000..b032fb6926 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java @@ -0,0 +1,166 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.merge.impl; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Logger; + +import org.apache.tuscany.das.rdb.config.wrapper.QualifiedColumn; +import org.apache.tuscany.das.rdb.graphbuilder.impl.MultiTableRegistry; +import org.apache.tuscany.das.rdb.graphbuilder.impl.TableRegistry; +import org.apache.tuscany.sdo.impl.ChangeSummaryImpl; + +import commonj.sdo.ChangeSummary; +import commonj.sdo.DataObject; +import commonj.sdo.Property; + +public class GraphMerger { + + private HashMap keys = new HashMap(); + + private TableRegistry registry = new MultiTableRegistry(); + + private static Logger logger = Logger.getLogger("GraphMerger"); + + //TODO lots of cleanup/design + public GraphMerger() { + // Empty Constructor + } + + public DataObject merge(List graphs) { + DataObject primaryGraph = (DataObject) graphs.get(0); + + Iterator i = graphs.iterator(); + if (i.hasNext()) + i.next(); + while (i.hasNext()) { + primaryGraph = merge(primaryGraph, (DataObject) i.next()); + } + + return primaryGraph; + } + + public DataObject merge(DataObject primary, DataObject secondary) { + addGraphToRegistry(primary); + + ChangeSummary summary = primary + .getDataGraph().getChangeSummary(); + summary.endLogging(); + Iterator i = secondary.getType().getProperties().iterator(); + + while (i.hasNext()) { + Property p = (Property) i.next(); + + Iterator objects = secondary.getList(p.getName()).iterator(); + while (objects.hasNext()) { + DataObject object = (DataObject) objects.next(); + createObjectWithSubtree(primary, p, object); + } + } + ((ChangeSummaryImpl)summary).resumeLogging(); + return primary; + } + + private void createObjectWithSubtree(DataObject root, Property p, + DataObject object) { + Object pk = getPrimaryKey(object); + + if (!registry.contains(object.getType().getName(), Collections + .singletonList(pk))) { + // logger.info("creating " + object.getType().getName() + " with pk " + pk); + DataObject newObject = root.createDataObject(p.getName()); + + + + Iterator attrs = object.getType().getProperties().iterator(); + while (attrs.hasNext()) { + Property attr = (Property) attrs.next(); + if ( attr.getType().isDataType()) { + newObject.set(attr.getName(), object.get(attr)); + } + } + registry.put(object.getType().getName(), Collections + .singletonList(pk), newObject); + + Iterator refs = object.getType().getProperties().iterator(); + while (refs.hasNext()) { + Property ref = (Property) refs.next(); + if ( !ref.getType().isDataType()) { + List refObjects; + if (!ref.isMany()) { + refObjects = Collections.singletonList(object.get(ref)); + } else { + refObjects = (List) object.get(ref); + } + + Iterator iter = refObjects.iterator(); + while (iter.hasNext()) { + DataObject refObject = (DataObject) iter.next(); + createObjectWithSubtree(root, refObject + .getContainmentProperty(), refObject); + + refObject = registry.get(refObject.getType().getName(), Collections.singletonList(getPrimaryKey(refObject))); + if (ref.isMany()) { + newObject.getList( + newObject.getType().getProperty(ref.getName())) + .add(refObject); + } else + newObject.set(newObject.getType().getProperty( + ref.getName()), refObject); + } + } + + } + + } + + } + + private void addGraphToRegistry(DataObject graph1) { + Iterator i = graph1.getType().getProperties().iterator(); + while (i.hasNext()) { + Property p = (Property) i.next(); + Iterator objects = graph1.getList(p).iterator(); + while (objects.hasNext()) { + DataObject object = (DataObject) objects.next(); + Object pk = object.get(getPrimaryKeyName(object)); + logger.finest("Adding object with pk " + pk + " to registry"); + registry.put(object.getType().getName(), Collections + .singletonList(pk), object); + } + } + } + + private Object getPrimaryKey(DataObject object) { + String pkName = getPrimaryKeyName(object); + return object.get(pkName); + } + + private String getPrimaryKeyName(DataObject object) { + return (String) keys.get(object.getType().getName()); + } + + public void addPrimaryKey(String key) { + QualifiedColumn column = new QualifiedColumn(key); + logger.finest("Adding " + column.getTableName() + " " + + column.getColumnName() + " to keys"); + keys.put(column.getTableName(), column.getColumnName()); + } +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/ConfigUtil.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/ConfigUtil.java new file mode 100644 index 0000000000..46db6ca728 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/ConfigUtil.java @@ -0,0 +1,51 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.util; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.tuscany.das.rdb.config.Config; +import org.apache.tuscany.das.rdb.config.ConfigFactory; +import org.apache.tuscany.sdo.util.SDOUtil; + +import commonj.sdo.helper.XMLHelper; + +/** + * Config util provides config-related utilities such as loading a Config + * instance from an InputStream + * + */ +public class ConfigUtil { + + public static Config loadConfig(InputStream configStream) { + + if (configStream == null) + throw new RuntimeException( + "Cannot load configuration from a null InputStream. Possibly caused by an incorrect config xml file name"); + + SDOUtil.registerStaticTypes(ConfigFactory.class); + XMLHelper helper = XMLHelper.INSTANCE; + + try { + return (Config) helper.load(configStream).getRootObject(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DataObjectUtil.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DataObjectUtil.java new file mode 100644 index 0000000000..7f96f9aef4 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DataObjectUtil.java @@ -0,0 +1,73 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.util; + +import java.util.Iterator; +import java.util.List; + +import commonj.sdo.ChangeSummary; +import commonj.sdo.DataObject; +import commonj.sdo.Property; +import commonj.sdo.ChangeSummary.Setting; +import commonj.sdo.helper.DataFactory; + +/** + */ +public class DataObjectUtil { + + //Utilities + public static DataObject getRestoredCopy(DataObject changedDO) { + DataObject changedCopy = getCopy(changedDO); + restoreAttributeValues(changedCopy, changedDO); + return changedCopy; + } + + public static DataObject getCopy(DataObject original) { + + DataObject copy = DataFactory.INSTANCE.create(original.getType()); + + //Fill in values + Iterator i = original.getType().getProperties().iterator(); + while (i.hasNext()) { + Property feature = (Property) i.next(); + copy.set(feature, original.get(feature)); + } + return copy; + } + + /** + * @param changedCopy + * @return + */ + private static void restoreAttributeValues(DataObject changedCopy, DataObject changedDO) { + + ChangeSummary changeSummary = changedDO.getDataGraph().getChangeSummary(); + List changes = changeSummary.getOldValues(changedDO); + if ( changes == null ) + return; + + Iterator i = changes.iterator(); + while (i.hasNext()) { + Setting s = (Setting) i.next(); + if ( s.getProperty().getType().isDataType() ) + changedCopy.set(s.getProperty(), s.getValue()); + } + } + + + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DebugFormatter.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DebugFormatter.java new file mode 100644 index 0000000000..ed2e1063d6 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DebugFormatter.java @@ -0,0 +1,34 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.util; + +import java.util.logging.Formatter; +import java.util.logging.LogRecord; + +public class DebugFormatter extends Formatter { + + public String format(LogRecord record) { + StringBuffer message = new StringBuffer(); + message.append("["); + message.append(record.getSourceClassName()); + message.append("] "); + message.append(record.getMessage()); + message.append("\n"); + return message.toString(); + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DebugUtil.java b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DebugUtil.java new file mode 100644 index 0000000000..745fe8cb7e --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/das/rdb/src/main/java/org/apache/tuscany/das/rdb/util/DebugUtil.java @@ -0,0 +1,66 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.das.rdb.util; + +import java.util.logging.ConsoleHandler; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; + +//TODO Restructure Logging +public class DebugUtil { + + private static StringBuffer buffer = new StringBuffer(); + private static final Logger logger = Logger.getAnonymousLogger(); + + static { + logger.setUseParentHandlers(false); + Handler h = new ConsoleHandler(); + h.setFormatter(new DebugFormatter()); + logger.addHandler(h); + } + public static void debugln(Class c, boolean flag, Object obj) { + + if ( flag ) { + logger.logp(Level.INFO, getClassName(c), null, obj.toString() ); + } + } + + public static void debug(Class c, boolean flag, Object obj) { + if ( flag ) { + System.out.print("[" + getClassName(c) + "] " + obj ); + } + } + + public static void buffer(boolean flag, Object obj) { + if ( flag ) + buffer.append(obj); + } + + public static void flushBuffer(Class c, boolean flag) { + if ( flag ) { + System.out.println("[" + getClassName(c) + "] " + buffer.toString()); + buffer = new StringBuffer(); + } + } + + private static String getClassName(Class c) { + String className = c.getName(); + return className.substring(className.lastIndexOf(".") + 1); + } + +} |