diff --git a/querydsl-jpa/src/main/java/com/mysema/query/jpa/hibernate/Constants.java b/querydsl-jpa/src/main/java/com/mysema/query/jpa/hibernate/Constants.java new file mode 100644 index 000000000..bd231ba41 --- /dev/null +++ b/querydsl-jpa/src/main/java/com/mysema/query/jpa/hibernate/Constants.java @@ -0,0 +1,27 @@ +package com.mysema.query.jpa.hibernate; + +import java.util.Arrays; +import java.util.List; + +public final class Constants { + + public static final List keywords = Arrays.asList( + "ABS","ALL","AND","ANY","AS","ASC","AVG","BETWEEN", + "BIT_LENGTH[51]","BOTH","BY","CASE","CHAR_LENGTH", + "CHARACTER_LENGTH","CLASS", + "COALESCE","CONCAT","COUNT","CURRENT_DATE","CURRENT_TIME", + "CURRENT_TIMESTAMP", + "DELETE","DESC","DISTINCT","ELSE","EMPTY","END","ENTRY", + "ESCAPE","EXISTS","FALSE","FETCH", + "FROM","GROUP","HAVING","IN","INDEX","INNER","IS","JOIN", + "KEY","LEADING","LEFT","LENGTH","LIKE", + "LOCATE","LOWER","MAX","MEMBER","MIN","MOD","NEW","NOT", + "NULL","NULLIF","OBJECT","OF","OR", + "ORDER","OUTER","POSITION","SELECT","SET","SIZE","SOME", + "SQRT","SUBSTRING","SUM","THEN", + "TRAILING","TRIM","TRUE","TYPE","UNKNOWN","UPDATE","UPPER", + "VALUE","WHEN","WHERE"); + + private Constants(){} + +} diff --git a/querydsl-jpa/src/main/java/com/mysema/query/jpa/hibernate/HibernateDomainExporter.java b/querydsl-jpa/src/main/java/com/mysema/query/jpa/hibernate/HibernateDomainExporter.java index 592b98f78..731470cc0 100644 --- a/querydsl-jpa/src/main/java/com/mysema/query/jpa/hibernate/HibernateDomainExporter.java +++ b/querydsl-jpa/src/main/java/com/mysema/query/jpa/hibernate/HibernateDomainExporter.java @@ -12,9 +12,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Stack; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; @@ -26,10 +29,20 @@ import org.slf4j.LoggerFactory; import com.mysema.codegen.CodeWriter; import com.mysema.codegen.JavaWriter; -import com.mysema.codegen.model.SimpleType; +import com.mysema.codegen.model.ClassType; +import com.mysema.codegen.model.Type; +import com.mysema.codegen.model.TypeCategory; +import com.mysema.query.QueryException; +import com.mysema.query.codegen.EmbeddableSerializer; +import com.mysema.query.codegen.EntitySerializer; import com.mysema.query.codegen.EntityType; +import com.mysema.query.codegen.Property; import com.mysema.query.codegen.Serializer; import com.mysema.query.codegen.SimpleSerializerConfig; +import com.mysema.query.codegen.SupertypeSerializer; +import com.mysema.query.codegen.TypeFactory; +import com.mysema.query.codegen.TypeMappings; +import com.sun.xml.internal.ws.util.StringUtils; /** * @author tiwe @@ -39,6 +52,8 @@ public class HibernateDomainExporter { private static final Logger logger = LoggerFactory.getLogger(HibernateDomainExporter.class); + private static final List propertyFields = Arrays.asList("property","many-to-one","one-to-one","component","dynamic-component","properties","any","map","set","list","bag","idbag","array","primitive-array"); + private final XMLInputFactory inFactory = XMLInputFactory.newInstance(); private final String namePrefix; @@ -47,39 +62,87 @@ public class HibernateDomainExporter { private final List entityTypes = new ArrayList(); + private final List embeddableTypes = new ArrayList(); + + private final List superTypes = new ArrayList(); + private final List hibernateXml; + private final TypeMappings typeMappings = new TypeMappings(); + + private final Serializer embeddableSerializer = new EmbeddableSerializer(typeMappings, Constants.keywords); + + private final Serializer entitySerializer = new EntitySerializer(typeMappings, Constants.keywords); + + private final Serializer supertypeSerializer = new SupertypeSerializer(typeMappings, Constants.keywords); + + private final TypeFactory typeFactory = new TypeFactory(); + public HibernateDomainExporter(String namePrefix, File targetFolder, File... hibernateXml){ this.namePrefix = namePrefix; this.targetFolder = targetFolder; this.hibernateXml = Arrays.asList(hibernateXml); } - public void execute() throws FileNotFoundException, XMLStreamException{ + public void execute() throws IOException { + // collect types + try { + collectTypes(); + } catch (SecurityException e) { + throw new QueryException(e); + } catch (XMLStreamException e) { + throw new QueryException(e); + } catch (ClassNotFoundException e) { + throw new QueryException(e); + } catch (NoSuchMethodException e) { + throw new QueryException(e); + } + + // TODO : merge supertype fields into subtypes + + // serialize them + serialize(superTypes, supertypeSerializer); + serialize(embeddableTypes, embeddableSerializer); + serialize(entityTypes, entitySerializer); + } + + private void serialize(List types, Serializer serializer) throws IOException { + for (EntityType entityType : types){ + Type type = typeMappings.getPathType(entityType, entityType, true); + String packageName = entityType.getPackageName(); + String className = packageName.length() > 0 ? (packageName + "." + type.getSimpleName()) : type.getSimpleName(); + write(serializer, className.replace('.', '/') + ".java", entityType); + } + } + + private void collectTypes() throws IOException, XMLStreamException, ClassNotFoundException, SecurityException, NoSuchMethodException { for (File xmlFile : hibernateXml){ InputStream in = new FileInputStream(xmlFile); XMLStreamReader reader = inFactory.createXMLStreamReader(in); try{ - EntityType entityType = null; + Stack types = new Stack(); + Class cl = null; while (true) { int event = reader.next(); if (event == START_ELEMENT) { String name = reader.getLocalName(); - if (name.equals("class")){ - String className = reader.getAttributeValue(null, "name"); - String packageName = className.substring(0, className.lastIndexOf(".")); - String simpleName = className.substring(packageName.length()); - entityType = new EntityType(namePrefix, new SimpleType(className, packageName, simpleName)); + if (name.equals("class") || name.endsWith("subclass")){ + cl = Class.forName(reader.getAttributeValue(null, "name")); + Type simpleType = new ClassType(TypeCategory.ENTITY, cl); + types.push(new EntityType(namePrefix, simpleType)); - }else if (name.equals("property")){ + }else if (propertyFields.contains(name)){ String propertyName = reader.getAttributeValue(null, "name"); - // TODO - } + Type propertyType = getType(cl, propertyName); + Property property = new Property(types.peek(), propertyName, propertyType); + types.peek().addProperty(property); + } }else if (event == END_ELEMENT){ String name = reader.getLocalName(); - if (name.equals("class")){ - entityTypes.add(entityType); + if (name.equals("class") || name.endsWith("subclass")){ + entityTypes.add(types.peek()); + types.pop(); } } else if (event == END_DOCUMENT) { break; @@ -90,8 +153,21 @@ public class HibernateDomainExporter { reader.close(); } } - - // serialize entity types + } + + private Type getType(Class cl, String propertyName) throws NoSuchMethodException { + try { + Field field = cl.getField(propertyName); + return typeFactory.create(field.getType(), field.getGenericType()); + } catch (NoSuchFieldException e) { + try{ + Method method = cl.getMethod("get"+StringUtils.capitalize(propertyName)); + return typeFactory.create(method.getReturnType(), method.getGenericReturnType()); + }catch(NoSuchMethodException e1){ + Method method = cl.getMethod("is"+StringUtils.capitalize(propertyName)); + return typeFactory.create(method.getReturnType(), method.getGenericReturnType()); + } + } } private void write(Serializer serializer, String path, EntityType type) throws IOException { diff --git a/querydsl-jpa/src/test/java/com/mysema/example/Contact.java b/querydsl-jpa/src/test/java/com/mysema/example/Contact.java new file mode 100644 index 000000000..78cc1b6dc --- /dev/null +++ b/querydsl-jpa/src/test/java/com/mysema/example/Contact.java @@ -0,0 +1,31 @@ +package com.mysema.example; + +public class Contact { + + private String firstName, lastName, email; + + 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 String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + +} diff --git a/querydsl-jpa/src/test/java/com/mysema/query/jpa/hibernate/HibernateDomainExporterTest.java b/querydsl-jpa/src/test/java/com/mysema/query/jpa/hibernate/HibernateDomainExporterTest.java new file mode 100644 index 000000000..6bb5180fe --- /dev/null +++ b/querydsl-jpa/src/test/java/com/mysema/query/jpa/hibernate/HibernateDomainExporterTest.java @@ -0,0 +1,27 @@ +package com.mysema.query.jpa.hibernate; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileUtils; +import org.junit.Test; + +public class HibernateDomainExporterTest { + + @Test + public void Execute() throws IOException { + File contact = new File("src/test/resources/contact.hbm.xml"); + HibernateDomainExporter exporter = new HibernateDomainExporter("Q", new File("target/gen"), contact); + exporter.execute(); + + File targetFile = new File("target/gen/com/mysema/example/QContact.java"); + assertTrue(targetFile.exists()); + String result = FileUtils.readFileToString(targetFile, "UTF-8"); + System.out.println(result); + assertTrue(result.contains("StringPath firstName")); + assertTrue(result.contains("StringPath lastName")); + } + +} diff --git a/querydsl-jpa/src/test/resources/contact.hbm.xml b/querydsl-jpa/src/test/resources/contact.hbm.xml new file mode 100644 index 000000000..e39712041 --- /dev/null +++ b/querydsl-jpa/src/test/resources/contact.hbm.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file