Index: trunk/fmgVen/src/com/fmguler/ven/QueryGenerator.java
===================================================================
--- trunk/fmgVen/src/com/fmguler/ven/QueryGenerator.java	(revision 27)
+++ trunk/fmgVen/src/com/fmguler/ven/QueryGenerator.java	(revision 28)
@@ -19,7 +19,10 @@
 
 import com.fmguler.ven.util.Convert;
+import com.fmguler.ven.util.VenList;
 import java.beans.PropertyDescriptor;
 import java.util.Date;
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 import org.springframework.beans.BeanWrapper;
@@ -33,4 +36,5 @@
     private Set domainPackages;
     private Set dbClasses;
+    private boolean debug = true;
 
     public QueryGenerator() {
@@ -45,6 +49,20 @@
     }
 
-    public String generateSelectQuery() {
-        return null;
+    /**
+     * Generates select query for the specified object class and specified joins.
+     * @param joins set of joins that the query will contain
+     * @param objectClass the object class to select from
+     * @return the select SQL query
+     */
+    public String generateSelectQuery(Class objectClass, Set joins) {
+        long t1 = System.currentTimeMillis();
+        String objectName = Convert.toSimpleName(objectClass.getName());
+        String tableName = Convert.toDB(objectName);
+        StringBuffer selectClause = new StringBuffer("select ");
+        StringBuffer fromClause = new StringBuffer("from " + tableName);
+        generateRecursively(0, tableName, objectName, objectClass, joins, selectClause, fromClause);
+        selectClause.append(" 1=1");
+        if (debug) System.out.println("Ven - query generation time = " + (System.currentTimeMillis() - t1));
+        return selectClause.toString() + " \n" + fromClause.toString();
     }
 
@@ -129,10 +147,10 @@
      * @return the delete SQL query
      */
-    public String generateDeleteQuery(Class objectClass){
+    public String generateDeleteQuery(Class objectClass) {
         StringBuffer query = new StringBuffer();
         query.append("delete from ").append(Convert.toDB(Convert.toSimpleName(objectClass.getName()))).append(" where id = :id;");
         return query.toString();
     }
-        
+
     /**
      * Generates sequence query for the specified object
@@ -147,5 +165,73 @@
 
     //--------------------------------------------------------------------------
+    //PRIVATE METHODS
+    //recursively generate select query
+    private void generateRecursively(int level, String tableName, String objectPath, Class objectClass, Set joins, StringBuffer selectClause, StringBuffer fromClause) {
+        BeanWrapper wr = new BeanWrapperImpl(objectClass);
+        PropertyDescriptor[] pdArr = wr.getPropertyDescriptors();
+
+        for (int i = 0; i < pdArr.length; i++) {
+            Class fieldClass = pdArr[i].getPropertyType(); //field class
+            String fieldName = pdArr[i].getName(); //field name
+            Object fieldValue = wr.getPropertyValue(fieldName);
+            String columnName = Convert.toDB(pdArr[i].getName()); //column name
+
+            //direct database class (Integer, String, Date, etc)
+            if (dbClasses.contains(fieldClass)) {
+                selectClause.append(tableName).append(".").append(columnName).append(" as ").append(tableName).append("_").append(columnName); //column
+                selectClause.append(", ");
+            }
+
+            //many to one association (object property)
+            if (fieldClass.getPackage() != null && domainPackages.contains(fieldClass.getPackage().getName()) && joinsContain(joins, objectPath + "." + fieldName)) {
+                String joinTableAlias = tableName + "_" + columnName; //alias for table to join since there can be multiple joins to the same table
+                String joinTable = Convert.toDB(Convert.toSimpleName(fieldClass.getName())); //table to join
+                fromClause.append(" left join ").append(joinTable).append(" ").append(joinTableAlias);
+                fromClause.append(" on ").append(joinTableAlias).append(".id = ").append(tableName).append(".").append(columnName).append("_id");
+                generateRecursively(++level, joinTableAlias, objectPath + "." + fieldName, fieldClass, joins, selectClause, fromClause);
+            }
+
+            //one to many association (list property)
+            if (fieldValue instanceof List && joinsContain(joins, objectPath + "." + fieldName)) {
+                Class elementClass = VenList.findElementClass((List)fieldValue);
+                String joinTableAlias = tableName + "_" + columnName; //alias for table to join since there can be multiple joins to the same table
+                String joinTable = Convert.toDB(Convert.toSimpleName(elementClass.getName())); //table to join
+                String joinField = Convert.toDB(findJoinField((List)fieldValue)); //field to join
+                fromClause.append(" left join ").append(joinTable).append(" ").append(joinTableAlias);
+                fromClause.append(" on ").append(joinTableAlias).append(".").append(joinField).append("_id = ").append(tableName).append(".id");
+                generateRecursively(++level, joinTableAlias, objectPath + "." + fieldName, elementClass, joins, selectClause, fromClause);
+            }
+        }
+    }
+
+    //check if the joins contain the specified join
+    private boolean joinsContain(Set joins, String join) {
+        Iterator it = joins.iterator();
+        while (it.hasNext()) {
+            String str = (String)it.next();
+            if (str.startsWith(join)) {
+                if (str.length() == join.length()) return true;
+                else if (str.charAt(join.length()) == '.') return true;
+            }
+        }
+        return false;
+    }
+
+    //return the join field of the elements in the list
+    private String findJoinField(List list) {
+        if (list instanceof VenList) {
+            return ((VenList)list).getJoinField();
+        } else {
+            //find according to 1.5 generic or some convention (e.g. parent_obj_id)
+            return null;
+        }
+    }
+
+    //--------------------------------------------------------------------------
     //SETTERS
+    /**
+     * Add the domain packages that will be considered persistent
+     * @param domainPackage the domain package
+     */
     public void addDomainPackage(String domainPackage) {
         domainPackages.add(domainPackage);
