summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.persistence.adapter.jdbc/src
diff options
context:
space:
mode:
Diffstat (limited to 'projects/net.wotonomy.persistence.adapter.jdbc/src')
-rw-r--r--projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/EOMapObjectStore.java116
-rw-r--r--projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCAdaptor.java11
-rw-r--r--projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCAdaptorException.java4
-rw-r--r--projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCContext.java10
-rw-r--r--projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/SimpleJDBCObjectStore.java69
-rw-r--r--projects/net.wotonomy.persistence.adapter.jdbc/src/test/java/net/wotonomy/jdbcadaptor/JDBCDBTest.java89
-rw-r--r--projects/net.wotonomy.persistence.adapter.jdbc/src/test/java/net/wotonomy/jdbcadaptor/Person.java59
7 files changed, 349 insertions, 9 deletions
diff --git a/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/EOMapObjectStore.java b/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/EOMapObjectStore.java
new file mode 100644
index 0000000..06dc280
--- /dev/null
+++ b/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/EOMapObjectStore.java
@@ -0,0 +1,116 @@
+package net.wotonomy.jdbcadaptor;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.wotonomy.control.ArrayFault;
+import net.wotonomy.control.EOEditingContext;
+import net.wotonomy.control.EOFetchSpecification;
+import net.wotonomy.control.EOGlobalID;
+import net.wotonomy.control.EOObjectStore;
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.internal.WotonomyException;
+
+/**
+ * Implementation of EOObjectStore backed by a single map
+ * @author bjculkin
+ *
+ */
+public class EOMapObjectStore extends EOObjectStore {
+ private Map<EOGlobalID, Object> data;
+
+ public EOMapObjectStore() {
+ super();
+
+ data = new HashMap<>();
+ }
+
+ public EOMapObjectStore(Map<EOGlobalID, Object> data) {
+ this.data = data;
+ }
+
+ public Map<EOGlobalID, Object> getData() {
+ return data;
+ }
+
+ public void setData(Map<EOGlobalID, Object> data) {
+ this.data = data;
+ }
+
+ @Override
+ public NSArray<?> arrayFaultWithSourceGlobalID(EOGlobalID aGlobalID, String aRelationship,
+ EOEditingContext aContext) {
+ return new ArrayFault(aGlobalID, aRelationship, aContext);
+ }
+
+ @Override
+ public Object faultForGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) {
+ return data.get(aGlobalID);
+ }
+
+ @Override
+ public Object faultForRawRow(Map aDictionary, String anEntityName, EOEditingContext aContext) {
+ // TODO: faults are not yet supported
+ throw new WotonomyException("Faults are not yet supported.");
+ }
+
+ @Override
+ public void initializeObject(Object eo, EOGlobalID aGlobalID, EOEditingContext aContext) {
+ // TODO is this right?
+ data.put(aGlobalID, eo);
+ aContext.recordObject(eo, aGlobalID);
+ }
+
+ @Override
+ public void invalidateAllObjects() {
+ // Does nothing
+ }
+
+ @Override
+ public void invalidateObjectsWithGlobalIDs(List aList) {
+ // Does nothing
+ }
+
+ @Override
+ public boolean isObjectLockedWithGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) {
+ // No locking
+ return false;
+ }
+
+ @Override
+ public void lockObjectWithGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) {
+ // No locking
+ }
+
+ @Override
+ public NSArray objectsForSourceGlobalID(EOGlobalID aGlobalID, String aRelationship, EOEditingContext aContext) {
+ // TODO: relationships are not yet supported
+ throw new WotonomyException("Relationships are not yet supported.");
+ }
+
+ @Override
+ public NSArray objectsWithFetchSpecification(EOFetchSpecification aFetchSpec, EOEditingContext aContext) {
+ throw new WotonomyException("Fetchspecs are not yet supported.");
+ }
+
+ @Override
+ public void refaultObject(Object anObject, EOGlobalID aGlobalID, EOEditingContext aContext) {
+ // TODO faults are not supported
+ initializeObject(anObject, aGlobalID, aContext);
+ }
+
+ @Override
+ public void saveChangesInEditingContext(EOEditingContext aContext) {
+ for (Object obj : aContext.insertedObjects()) {
+ EOGlobalID key = aContext.globalIDForObject(obj);
+ data.put(key, obj);
+ }
+ for (Object obj : aContext.deletedObjects()) {
+ EOGlobalID key = aContext.globalIDForObject(obj);
+ data.remove(key);
+ }
+ // No need to handle updates
+ }
+
+}
diff --git a/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCAdaptor.java b/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCAdaptor.java
index f3d848c..1a67d6d 100644
--- a/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCAdaptor.java
+++ b/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCAdaptor.java
@@ -34,7 +34,7 @@ public class JDBCAdaptor extends EOAdaptor {
protected EOSQLExpressionFactory _expressionFactory;
protected String _driverName;
- protected NSDictionary _jdbcInfo;
+ protected NSDictionary<String, String> _jdbcInfo;
/**
* Creates a new instance.
@@ -45,14 +45,15 @@ public class JDBCAdaptor extends EOAdaptor {
super(name);
}
- public void setConnectionDictionary(NSDictionary dict) {
+ @SuppressWarnings("unchecked")
+ public void setConnectionDictionary(NSDictionary<String, Object> dict) {
super.setConnectionDictionary(dict);
if (dict.objectForKey("driver") != null)
_driverName = (String) dict.objectForKey("driver");
else
throw new JDBCAdaptorException("Connection dictionary must have a 'driver' key.", null);
if (dict.objectForKey("jdbc2Info") != null)
- _jdbcInfo = (NSDictionary) dict.objectForKey("jdbc2Info");
+ _jdbcInfo = (NSDictionary<String, String>) dict.objectForKey("jdbc2Info");
else
throw new JDBCAdaptorException("Connection dictionary must have a 'jdbc2Info' key.", null);
}
@@ -85,7 +86,7 @@ public class JDBCAdaptor extends EOAdaptor {
*
* @see net.wotonomy.access.EOAdaptor#defaultExpressionClass()
*/
- public Class defaultExpressionClass() {
+ public Class<JDBCExpression> defaultExpressionClass() {
return JDBCExpression.class;
}
@@ -115,7 +116,7 @@ public class JDBCAdaptor extends EOAdaptor {
return _driverName;
}
- public NSDictionary jdbcInfo() {
+ public NSDictionary<String, String> jdbcInfo() {
return _jdbcInfo;
}
diff --git a/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCAdaptorException.java b/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCAdaptorException.java
index 412c0a1..ea9df38 100644
--- a/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCAdaptorException.java
+++ b/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCAdaptorException.java
@@ -29,7 +29,7 @@ import net.wotonomy.access.EOGeneralAdaptorException;
* @version $Revision: 903 $
*/
public class JDBCAdaptorException extends EOGeneralAdaptorException {
-
+ private static final long serialVersionUID = -2677311934036267760L;
protected SQLException _sqlException;
/**
@@ -38,6 +38,7 @@ public class JDBCAdaptorException extends EOGeneralAdaptorException {
*/
public JDBCAdaptorException(String msg, SQLException sqlex) {
super(msg);
+ initCause(sqlex);
_sqlException = sqlex;
}
@@ -47,6 +48,7 @@ public class JDBCAdaptorException extends EOGeneralAdaptorException {
*/
public JDBCAdaptorException(SQLException sqlex) {
super(sqlex.getMessage());
+ initCause(sqlex);
_sqlException = sqlex;
}
diff --git a/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCContext.java b/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCContext.java
index 9e6df6c..87c33fe 100644
--- a/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCContext.java
+++ b/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/JDBCContext.java
@@ -25,6 +25,7 @@ import java.sql.SQLException;
import net.wotonomy.access.EOAdaptor;
import net.wotonomy.access.EOAdaptorChannel;
import net.wotonomy.access.EOAdaptorContext;
+import net.wotonomy.foundation.NSDictionary;
/**
* Concrete implementation of EOAdaptorContext for use with JDBC.
@@ -51,11 +52,14 @@ public class JDBCContext extends EOAdaptorContext {
if (_jdbcConnection != null && !_jdbcConnection.isClosed())
throw new JDBCAdaptorException("Attempt to connect when already connected.", null);
Class.forName(((JDBCAdaptor) adaptor()).driverName());
- String url = (String) adaptor().connectionDictionary().objectForKey("URL");
+ NSDictionary<String, Object> connectionDictionary = adaptor().connectionDictionary();
+ String url = (String) connectionDictionary.objectForKey("URL");
Driver driver = DriverManager.getDriver(url);
java.util.Properties props = new java.util.Properties();
- props.setProperty("user", (String) adaptor().connectionDictionary().objectForKey("username"));
- props.setProperty("password", (String) adaptor().connectionDictionary().objectForKey("password"));
+ if (connectionDictionary.containsKey("username"))
+ props.setProperty("user", (String) connectionDictionary.objectForKey("username"));
+ if (connectionDictionary.containsKey("password"))
+ props.setProperty("password", (String) connectionDictionary.objectForKey("password"));
_jdbcConnection = driver.connect(url, props);
_jdbcConnection.setAutoCommit(false);
} catch (SQLException ex) {
diff --git a/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/SimpleJDBCObjectStore.java b/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/SimpleJDBCObjectStore.java
new file mode 100644
index 0000000..67bbc0c
--- /dev/null
+++ b/projects/net.wotonomy.persistence.adapter.jdbc/src/main/java/net/wotonomy/jdbcadaptor/SimpleJDBCObjectStore.java
@@ -0,0 +1,69 @@
+package net.wotonomy.jdbcadaptor;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import net.wotonomy.control.AbstractObjectStore;
+import net.wotonomy.control.EOEditingContext;
+import net.wotonomy.control.EOFetchSpecification;
+import net.wotonomy.control.EOGlobalID;
+import net.wotonomy.control.EOObjectStore;
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.internal.WotonomyException;
+
+/**
+ * A simple EOObjectStore that uses JDBC
+ * @author bjculkin
+ *
+ */
+public class SimpleJDBCObjectStore extends AbstractObjectStore {
+
+ @Override
+ protected Comparable timestampForData(Map aDataMap) {
+ return null;
+ }
+
+ @Override
+ protected EOGlobalID globalIDForData(Map aDataMap) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected String entityForGlobalIDOrObject(EOGlobalID aGlobalID, Object anObject) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Collection changedKeysForObject(Object anObject) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Map readObject(EOGlobalID aGlobalID, Collection keys) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Map insertObject(EOGlobalID aGlobalID, Map aDataMap) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Object updateObject(EOGlobalID aGlobalID, Map aDataMap) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Object deleteObject(EOGlobalID aGlobalID) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/projects/net.wotonomy.persistence.adapter.jdbc/src/test/java/net/wotonomy/jdbcadaptor/JDBCDBTest.java b/projects/net.wotonomy.persistence.adapter.jdbc/src/test/java/net/wotonomy/jdbcadaptor/JDBCDBTest.java
new file mode 100644
index 0000000..5af3bff
--- /dev/null
+++ b/projects/net.wotonomy.persistence.adapter.jdbc/src/test/java/net/wotonomy/jdbcadaptor/JDBCDBTest.java
@@ -0,0 +1,89 @@
+package net.wotonomy.jdbcadaptor;
+
+import java.sql.SQLException;
+
+import junit.framework.TestCase;
+import net.wotonomy.access.EODatabase;
+import net.wotonomy.access.EODatabaseContext;
+import net.wotonomy.control.EOClassDescription;
+import net.wotonomy.control.EOEditingContext;
+import net.wotonomy.control.EOTemporaryGlobalID;
+import net.wotonomy.foundation.NSDictionary;
+
+public class JDBCDBTest extends TestCase {
+ public void testJDBCContextH2() throws SQLException, ClassNotFoundException {
+ String jdbcURL = "jdbc:h2:mem:test";
+
+ // Feels a bit weird not to put anything here, but I don't think we need to
+ NSDictionary<String, String> jdbcInfo = new NSDictionary<>();
+
+ NSDictionary<String, Object> connDict = new NSDictionary<>();
+ connDict.put("driver", "org.h2.Driver");
+ connDict.put("jdbc2Info", jdbcInfo);
+ connDict.put("URL", jdbcURL);
+ JDBCAdaptor adaptor = new JDBCAdaptor("JDBC");
+ adaptor.setConnectionDictionary(connDict);
+ adaptor.assertConnectionDictionaryIsValid();
+
+ EODatabase db = new EODatabase(adaptor);
+ EODatabaseContext dbCtx = new EODatabaseContext(db);
+ ((JDBCContext)dbCtx.adaptorContext()).connect();
+
+ EOEditingContext editCtx = new EOEditingContext(dbCtx);
+
+ EOClassDescription<Person> personDesc = EOClassDescription.classDescriptionForClass(Person.class);
+ EOTemporaryGlobalID tempGID = new EOTemporaryGlobalID();
+ Person person = personDesc.createInstanceWithEditingContext(editCtx, tempGID);
+
+ person.setFirstName("John");
+ person.setLastName("Doe");
+ person.setAge(25);
+
+ editCtx.saveChanges();
+
+ Person newPerson = (Person) editCtx.objectForGlobalID(tempGID);
+ assertEquals(person, newPerson);
+ }
+
+ public void testJDBCContextPostgres() throws SQLException, ClassNotFoundException {
+ String jdbcURL = "jdbc:postgresql:wotonomy";
+
+ // Feels a bit weird not to put anything here, but I don't think we need to
+ NSDictionary<String, String> jdbcInfo = new NSDictionary<>();
+
+ NSDictionary<String, Object> connDict = new NSDictionary<>();
+ connDict.put("driver", "org.postgresql.Driver");
+ connDict.put("jdbc2Info", jdbcInfo);
+ connDict.put("URL", jdbcURL);
+ connDict.put("username", "wotonomy");
+ connDict.put("password", "wotonomy");
+
+ JDBCAdaptor adaptor = new JDBCAdaptor("JDBC");
+ adaptor.setConnectionDictionary(connDict);
+ adaptor.assertConnectionDictionaryIsValid();
+
+ EODatabase db = new EODatabase(adaptor);
+ EODatabaseContext dbCtx = new EODatabaseContext(db);
+ ((JDBCContext)dbCtx.adaptorContext()).connect();
+
+ EOEditingContext editCtx = new EOEditingContext(dbCtx);
+
+ EOClassDescription<Person> personDesc = EOClassDescription.classDescriptionForClass(Person.class);
+
+ EOTemporaryGlobalID tempGID = new EOTemporaryGlobalID();
+ Person person = personDesc.createInstanceWithEditingContext(editCtx, tempGID);
+
+ person.setFirstName("John");
+ person.setLastName("Doe");
+ person.setAge(25);
+
+ editCtx.saveChanges();
+ editCtx.invalidateAllObjects();
+
+ ((JDBCContext)dbCtx.adaptorContext()).commitTransaction();
+ //editCtx.reset();
+
+ Person newPerson = (Person) editCtx.objectForGlobalID(tempGID);
+ assertEquals(person, newPerson);
+ }
+} \ No newline at end of file
diff --git a/projects/net.wotonomy.persistence.adapter.jdbc/src/test/java/net/wotonomy/jdbcadaptor/Person.java b/projects/net.wotonomy.persistence.adapter.jdbc/src/test/java/net/wotonomy/jdbcadaptor/Person.java
new file mode 100644
index 0000000..d42c77c
--- /dev/null
+++ b/projects/net.wotonomy.persistence.adapter.jdbc/src/test/java/net/wotonomy/jdbcadaptor/Person.java
@@ -0,0 +1,59 @@
+package net.wotonomy.jdbcadaptor;
+
+import java.util.Objects;
+
+public class Person {
+ private String firstName;
+ private String lastName;
+
+ private int age;
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(age, firstName, lastName);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Person other = (Person) obj;
+ return age == other.age && Objects.equals(firstName, other.firstName)
+ && Objects.equals(lastName, other.lastName);
+ }
+
+ @Override
+ public String toString() {
+ return "Person [firstName=" + firstName + ", lastName=" + lastName + ", age=" + age + "]";
+ }
+
+
+} \ No newline at end of file