summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn O. Pearce <sop@google.com>2010-06-01 13:56:37 -0700
committerShawn O. Pearce <sop@google.com>2010-06-01 13:56:37 -0700
commitdfbd70cb8517a0d1fff899e925ca6e9340ce32b7 (patch)
treee4ce0ddd30c881ce6317f332506da5f0850dc85a
parentc57426c28c2a2d419cf5bae10469a8a225fa0efa (diff)
downloadgwtorm-dfbd70cb8517a0d1fff899e925ca6e9340ce32b7.tar.gz
Refactor SchemaGen to be reused for NoSQL backends
The entire schema implementation is just about constructing the various methods that return the Access implementations for each relation. This isn't unique to JDBC and can easily be reused for a NoSQL backend as-is, if we properly abstract out the base class it uses and the method to obtain each Access implementation as its required by the schema code generator. Change-Id: If9b1d63b1b83fafb1eab14b64861cd26dde73d2e Signed-off-by: Shawn O. Pearce <sop@google.com>
-rw-r--r--src/main/java/com/google/gwtorm/jdbc/Database.java17
-rw-r--r--src/main/java/com/google/gwtorm/jdbc/gen/AccessGen.java21
-rw-r--r--src/main/java/com/google/gwtorm/server/SchemaGen.java (renamed from src/main/java/com/google/gwtorm/jdbc/gen/SchemaGen.java)55
3 files changed, 56 insertions, 37 deletions
diff --git a/src/main/java/com/google/gwtorm/jdbc/Database.java b/src/main/java/com/google/gwtorm/jdbc/Database.java
index aa48022..976998b 100644
--- a/src/main/java/com/google/gwtorm/jdbc/Database.java
+++ b/src/main/java/com/google/gwtorm/jdbc/Database.java
@@ -14,11 +14,13 @@
package com.google.gwtorm.jdbc;
+import com.google.gwtorm.client.Access;
import com.google.gwtorm.client.KeyUtil;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.Schema;
import com.google.gwtorm.client.SchemaFactory;
-import com.google.gwtorm.jdbc.gen.SchemaGen;
+import com.google.gwtorm.jdbc.gen.AccessGen;
+import com.google.gwtorm.schema.RelationModel;
import com.google.gwtorm.schema.SchemaModel;
import com.google.gwtorm.schema.java.JavaSchemaModel;
import com.google.gwtorm.schema.sql.DialectH2;
@@ -27,6 +29,7 @@ import com.google.gwtorm.schema.sql.DialectPostgreSQL;
import com.google.gwtorm.schema.sql.SqlDialect;
import com.google.gwtorm.server.GeneratedClassLoader;
import com.google.gwtorm.server.SchemaConstructorGen;
+import com.google.gwtorm.server.SchemaGen;
import com.google.gwtorm.server.StandardKeyEncoder;
import java.sql.Connection;
@@ -105,9 +108,17 @@ public class Database<T extends Schema> implements SchemaFactory<T> {
}
@SuppressWarnings("unchecked")
- private Class<T> generate(SqlDialect dialect,
+ private Class<T> generate(final SqlDialect dialect,
final GeneratedClassLoader loader) throws OrmException {
- return (Class<T>) new SchemaGen(loader, schemaModel, dialect).create();
+ return new SchemaGen(loader, schemaModel, JdbcSchema.class,
+ new SchemaGen.AccessGenerator() {
+ @Override
+ public <A extends Access<?, ?>> Class<A> create(
+ GeneratedClassLoader loader, RelationModel rm)
+ throws OrmException {
+ return new AccessGen(loader, rm, dialect).create();
+ }
+ }).create();
}
SqlDialect getDialect() {
diff --git a/src/main/java/com/google/gwtorm/jdbc/gen/AccessGen.java b/src/main/java/com/google/gwtorm/jdbc/gen/AccessGen.java
index f217455..f8496de 100644
--- a/src/main/java/com/google/gwtorm/jdbc/gen/AccessGen.java
+++ b/src/main/java/com/google/gwtorm/jdbc/gen/AccessGen.java
@@ -61,7 +61,6 @@ public class AccessGen implements Opcodes {
}
private final GeneratedClassLoader classLoader;
- private final SchemaGen.RelationGen info;
private final RelationModel model;
private final SqlDialect dialect;
@@ -73,16 +72,15 @@ public class AccessGen implements Opcodes {
public AccessGen(final GeneratedClassLoader loader,
- final SchemaGen.RelationGen ri) {
+ final RelationModel rm, final SqlDialect sd) {
classLoader = loader;
- info = ri;
- model = info.model;
- dialect = ri.getDialect();
+ model = rm;
+ dialect = sd;
entityType =
Type.getObjectType(model.getEntityTypeClassName().replace('.', '/'));
}
- public void defineClass() throws OrmException {
+ public <A extends Access<?, ?>> Class<A> create() throws OrmException {
init();
implementConstructor();
implementGetString("getRelationName", model.getRelationName());
@@ -123,9 +121,18 @@ public class AccessGen implements Opcodes {
cw.visitEnd();
classLoader.defineClass(implClassName, cw.toByteArray());
- info.accessClassName = implClassName;
+ return loadClass();
}
+ @SuppressWarnings("unchecked")
+ private <A extends Access<?, ?>> Class<A> loadClass() throws OrmException {
+ try {
+ final Class<?> c = Class.forName(implClassName, false, classLoader);
+ return (Class<A>) c;
+ } catch (ClassNotFoundException err) {
+ throw new OrmException("Cannot load generated class", err);
+ }
+ }
private void init() {
superTypeName = Type.getInternalName(JdbcAccess.class);
diff --git a/src/main/java/com/google/gwtorm/jdbc/gen/SchemaGen.java b/src/main/java/com/google/gwtorm/server/SchemaGen.java
index fc46f9a..d6aa052 100644
--- a/src/main/java/com/google/gwtorm/jdbc/gen/SchemaGen.java
+++ b/src/main/java/com/google/gwtorm/server/SchemaGen.java
@@ -12,8 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gwtorm.jdbc.gen;
+package com.google.gwtorm.server;
+import com.google.gwtorm.client.Access;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.Schema;
import com.google.gwtorm.jdbc.Database;
@@ -22,8 +23,6 @@ import com.google.gwtorm.schema.RelationModel;
import com.google.gwtorm.schema.SequenceModel;
import com.google.gwtorm.schema.Util;
import com.google.gwtorm.schema.java.JavaSchemaModel;
-import com.google.gwtorm.schema.sql.SqlDialect;
-import com.google.gwtorm.server.GeneratedClassLoader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
@@ -34,21 +33,28 @@ import java.util.ArrayList;
import java.util.List;
/** Generates a concrete implementation of a {@link Schema} extension. */
-public class SchemaGen implements Opcodes {
+public class SchemaGen<S extends AbstractSchema> implements Opcodes {
+ public interface AccessGenerator {
+ <A extends Access<?, ?>> Class<A> create(GeneratedClassLoader loader,
+ RelationModel rm) throws OrmException;
+ }
+
private final GeneratedClassLoader classLoader;
private final JavaSchemaModel schema;
- private final SqlDialect dialect;
+ private final Class<S> schemaSuperClass;
+ private final AccessGenerator accessGen;
private List<RelationGen> relations;
private ClassWriter cw;
- private String superTypeName;
private String implClassName;
private String implTypeName;
public SchemaGen(final GeneratedClassLoader loader,
- final JavaSchemaModel schemaModel, final SqlDialect sqlDialect) {
+ final JavaSchemaModel schemaModel, final Class<S> superType,
+ final AccessGenerator ag) {
classLoader = loader;
schema = schemaModel;
- dialect = sqlDialect;
+ schemaSuperClass = superType;
+ accessGen = ag;
}
public Class<Schema> create() throws OrmException {
@@ -89,20 +95,19 @@ public class SchemaGen implements Opcodes {
private void defineRelationClasses() throws OrmException {
relations = new ArrayList<RelationGen>();
for (final RelationModel rel : schema.getRelations()) {
- final RelationGen g = new RelationGen(rel);
- relations.add(g);
- new AccessGen(classLoader, g).defineClass();
+ final Class<? extends Access> a = accessGen.create(classLoader, rel);
+ relations.add(new RelationGen(rel, a));
}
}
private void init() {
- superTypeName = Type.getInternalName(JdbcSchema.class);
implClassName = getSchemaClassName() + "_Schema_" + Util.createRandomName();
implTypeName = implClassName.replace('.', '/');
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- cw.visit(V1_3, ACC_PUBLIC | ACC_FINAL | ACC_SUPER, implTypeName, null,
- superTypeName, new String[] {getSchemaClassName().replace('.', '/')});
+ cw.visit(V1_3, ACC_PUBLIC | ACC_FINAL | ACC_SUPER, implTypeName, null, Type
+ .getInternalName(schemaSuperClass), new String[] {getSchemaClassName()
+ .replace('.', '/')});
}
private void implementRelationFields() {
@@ -122,7 +127,8 @@ public class SchemaGen implements Opcodes {
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
- mv.visitMethodInsn(INVOKESPECIAL, superTypeName, consName, consDesc);
+ mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(schemaSuperClass),
+ consName, consDesc);
for (final RelationGen info : relations) {
mv.visitVarInsn(ALOAD, 0);
@@ -154,9 +160,9 @@ public class SchemaGen implements Opcodes {
mv.visitVarInsn(ALOAD, 0);
mv.visitLdcInsn(seq.getSequenceName());
- mv.visitMethodInsn(INVOKEVIRTUAL, superTypeName, "nextLong", Type
- .getMethodDescriptor(Type.getType(Long.TYPE), new Type[] {Type
- .getType(String.class)}));
+ mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(schemaSuperClass),
+ "nextLong", Type.getMethodDescriptor(Type.getType(Long.TYPE),
+ new Type[] {Type.getType(String.class)}));
if (retType.getSize() == 1) {
mv.visitInsn(L2I);
mv.visitInsn(IRETURN);
@@ -174,21 +180,16 @@ public class SchemaGen implements Opcodes {
}
}
- class RelationGen {
+ private class RelationGen {
final RelationModel model;
- String accessClassName;
- Type accessType;
+ final Type accessType;
- RelationGen(final RelationModel model) {
+ RelationGen(final RelationModel model, final Class<?> accessClass) {
this.model = model;
- }
-
- SqlDialect getDialect() {
- return SchemaGen.this.dialect;
+ this.accessType = Type.getType(accessClass);
}
void implementField() {
- accessType = Type.getObjectType(accessClassName.replace('.', '/'));
cw.visitField(ACC_PRIVATE | ACC_FINAL, getAccessInstanceFieldName(),
accessType.getDescriptor(), null, null).visitEnd();
}