Index: /trunk/SchedulingSystem/lib/nblibraries.properties
===================================================================
--- /trunk/SchedulingSystem/lib/nblibraries.properties	(revision 20)
+++ /trunk/SchedulingSystem/lib/nblibraries.properties	(revision 30)
@@ -11,4 +11,8 @@
     ${base}/spring-framework3/commons-logging-1.1.jar;\
     ${base}/spring-framework3/org.springframework.core-3.0.3.RELEASE.jar;\
+    ${base}/spring-framework3/org.springframework.beans-3.0.3.RELEASE.jar;\
+    ${base}/spring-framework3/org.springframework.context-3.0.3.RELEASE.jar;\
+    ${base}/spring-framework3/org.springframework.expression-3.0.3.RELEASE.jar;\
+    ${base}/spring-framework3/org.springframework.asm-3.0.3.RELEASE.jar;\
     ${base}/spring-framework3/org.springframework.jdbc-3.0.3.RELEASE.jar;\
     ${base}/spring-framework3/org.springframework.transaction-3.0.3.RELEASE.jar;\
Index: /trunk/fmgVen/etc/license/license-ven-apache20.txt
===================================================================
--- /trunk/fmgVen/etc/license/license-ven-apache20.txt	(revision 30)
+++ /trunk/fmgVen/etc/license/license-ven-apache20.txt	(revision 30)
@@ -0,0 +1,21 @@
+<#if licenseFirst??>
+${licenseFirst}
+</#if>
+${licensePrefix} fmgVen - A Convention over Configuration Java ORM Tool
+${licensePrefix} Copyright ${date?date?string("yyyy")} Fatih Mehmet Güler
+${licensePrefix}
+${licensePrefix} Licensed under the Apache License, Version 2.0 (the "License");
+${licensePrefix} you may not use this file except in compliance with the License.
+${licensePrefix} You may obtain a copy of the License at
+${licensePrefix}
+${licensePrefix}      http://www.apache.org/licenses/LICENSE-2.0
+${licensePrefix}
+${licensePrefix} Unless required by applicable law or agreed to in writing, software
+${licensePrefix} distributed under the License is distributed on an "AS IS" BASIS,
+${licensePrefix} WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+${licensePrefix} See the License for the specific language governing permissions and
+${licensePrefix} limitations under the License.
+${licensePrefix} under the License.
+<#if licenseLast??>
+${licenseLast}
+</#if>
Index: /trunk/fmgVen/etc/test-db/test-db-changelog.xml
===================================================================
--- /trunk/fmgVen/etc/test-db/test-db-changelog.xml	(revision 30)
+++ /trunk/fmgVen/etc/test-db/test-db-changelog.xml	(revision 30)
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog logicalFilePath="database-schema.xml" xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">
+    <changeSet author="fmguler" id="init">
+    </changeSet>
+    <changeSet author="fmguler" id="0">
+        <tagDatabase tag="tag-init"/>
+    </changeSet>
+    <!-- TEST SCHEMA >> -->
+    <changeSet author="fmguler" id="1">
+        <createTable schemaName="public" tableName="some_domain_object">
+            <column autoIncrement="true" name="id" type="serial">
+                <constraints nullable="false" primaryKey="true" primaryKeyName="some_domain_object_pkey"/>
+            </column>
+            <column name="name" type="VARCHAR(100)"/>
+            <column name="description" type="TEXT(2147483647)"/>
+            <column name="date" type="TIMESTAMP WITHOUT TIME ZONE"/>
+            <column name="another_domain_object_id" type="int"/>
+        </createTable>
+    </changeSet>
+    <changeSet author="fmguler" id="2">
+        <createTable schemaName="public" tableName="another_domain_object">
+            <column autoIncrement="true" name="id" type="serial">
+                <constraints nullable="false" primaryKey="true" primaryKeyName="another_domain_object_pkey"/>
+            </column>
+            <column name="name" type="VARCHAR(100)"/>
+            <column name="description" type="TEXT(2147483647)"/>
+            <column name="date" type="TIMESTAMP WITHOUT TIME ZONE"/>
+            <column name="some_domain_object_id" type="int"/>
+        </createTable>
+    </changeSet>
+    <changeSet author="fmguler" id="3">
+        <tagDatabase tag="tag-no-data"/>
+    </changeSet>
+    <changeSet author="fmguler" id="4">
+        <insert schemaName="public" tableName="some_domain_object">
+            <column name="name" value="sdo1"/>
+            <column name="description" value="sdo desc1"/>
+            <column name="date" value="2010-10-13"/>
+            <column name="another_domain_object_id" value="1"/>
+        </insert>
+        <rollback>
+            delete from some_domain_object;
+        </rollback>
+    </changeSet>
+    <changeSet author="fmguler" id="5">
+        <insert schemaName="public" tableName="another_domain_object">
+            <column name="name" value="ado1"/>
+            <column name="description" value="ado desc1"/>
+            <column name="date" value="2011-01-19"/>
+            <column name="some_domain_object_id" value="1"/>
+        </insert>
+        <insert schemaName="public" tableName="another_domain_object">
+            <column name="name" value="ado2"/>
+            <column name="description" value="ado desc2"/>
+            <column name="date" value="2011-02-09"/>
+            <column name="some_domain_object_id" value="1"/>
+        </insert>
+        <rollback>
+            delete from another_domain_object;
+        </rollback>
+    </changeSet>
+    <changeSet author="fmguler" id="6">
+        <tagDatabase tag="tag-data"/>
+    </changeSet>
+    <!-- << TEST SCHEMA -->
+</databaseChangeLog>
Index: /trunk/fmgVen/lib/nblibraries.properties
===================================================================
--- /trunk/fmgVen/lib/nblibraries.properties	(revision 20)
+++ /trunk/fmgVen/lib/nblibraries.properties	(revision 30)
@@ -5,2 +5,11 @@
 libs.CopyLibs.classpath=\
     ${base}/CopyLibs/org-netbeans-modules-java-j2seproject-copylibstask.jar
+libs.Test.classpath=\
+    ${base}/test/postgresql-8.4-701.jdbc3.jar;\
+    ${base}/test/liquibase-1.9.5.jar
+libs.Ven.classpath=\
+    ${base}/ven/spring-beans.jar;\
+    ${base}/ven/spring-core.jar;\
+    ${base}/ven/spring-jdbc.jar;\
+    ${base}/ven/spring-tx.jar;\
+    ${base}/ven/commons-logging-1.1.1.jar
Index: /trunk/fmgVen/nbproject/build-impl.xml
===================================================================
--- /trunk/fmgVen/nbproject/build-impl.xml	(revision 20)
+++ /trunk/fmgVen/nbproject/build-impl.xml	(revision 30)
@@ -80,4 +80,41 @@
     </target>
     <target depends="-pre-init,-init-private,-init-libraries,-init-user,-init-project,-init-macrodef-property" name="-do-init">
+        <j2seproject1:property name="platform.home" value="platforms.${platform.active}.home"/>
+        <j2seproject1:property name="platform.bootcp" value="platforms.${platform.active}.bootclasspath"/>
+        <j2seproject1:property name="platform.compiler" value="platforms.${platform.active}.compile"/>
+        <j2seproject1:property name="platform.javac.tmp" value="platforms.${platform.active}.javac"/>
+        <condition property="platform.javac" value="${platform.home}/bin/javac">
+            <equals arg1="${platform.javac.tmp}" arg2="$${platforms.${platform.active}.javac}"/>
+        </condition>
+        <property name="platform.javac" value="${platform.javac.tmp}"/>
+        <j2seproject1:property name="platform.java.tmp" value="platforms.${platform.active}.java"/>
+        <condition property="platform.java" value="${platform.home}/bin/java">
+            <equals arg1="${platform.java.tmp}" arg2="$${platforms.${platform.active}.java}"/>
+        </condition>
+        <property name="platform.java" value="${platform.java.tmp}"/>
+        <j2seproject1:property name="platform.javadoc.tmp" value="platforms.${platform.active}.javadoc"/>
+        <condition property="platform.javadoc" value="${platform.home}/bin/javadoc">
+            <equals arg1="${platform.javadoc.tmp}" arg2="$${platforms.${platform.active}.javadoc}"/>
+        </condition>
+        <property name="platform.javadoc" value="${platform.javadoc.tmp}"/>
+        <condition property="platform.invalid" value="true">
+            <or>
+                <contains string="${platform.javac}" substring="$${platforms."/>
+                <contains string="${platform.java}" substring="$${platforms."/>
+                <contains string="${platform.javadoc}" substring="$${platforms."/>
+            </or>
+        </condition>
+        <fail unless="platform.home">Must set platform.home</fail>
+        <fail unless="platform.bootcp">Must set platform.bootcp</fail>
+        <fail unless="platform.java">Must set platform.java</fail>
+        <fail unless="platform.javac">Must set platform.javac</fail>
+        <fail if="platform.invalid">
+ The J2SE Platform is not correctly set up.
+ Your active platform is: ${platform.active}, but the corresponding property "platforms.${platform.active}.home" is not found in the project's properties files. 
+ Either open the project in the IDE and setup the Platform with the same name or add it manually.
+ For example like this:
+     ant -Duser.properties.file=&lt;path_to_property_file&gt; jar (where you put the property "platforms.${platform.active}.home" in a .properties file)
+  or ant -Dplatforms.${platform.active}.home=&lt;path_to_JDK_home&gt; jar (where no properties file is used) 
+  </fail>
         <available file="${manifest.file}" property="manifest.available"/>
         <available file="${application.splash}" property="splashscreen.available"/>
@@ -199,5 +236,4 @@
             <length length="0" string="${endorsed.classpath}" when="greater"/>
         </condition>
-        <property name="javac.fork" value="false"/>
         <property name="jar.index" value="false"/>
         <available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/>
@@ -245,5 +281,5 @@
                 <mkdir dir="${empty.dir}"/>
                 <mkdir dir="@{apgeneratedsrcdir}"/>
-                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" executable="${platform.javac}" fork="yes" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
                     <src>
                         <dirset dir="@{gensrcdir}" erroronmissingdir="false">
@@ -284,5 +320,5 @@
                 <property location="${build.dir}/empty" name="empty.dir"/>
                 <mkdir dir="${empty.dir}"/>
-                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" executable="${platform.javac}" fork="yes" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
                     <src>
                         <dirset dir="@{gensrcdir}" erroronmissingdir="false">
@@ -335,5 +371,5 @@
             <attribute default="**" name="testincludes"/>
             <sequential>
-                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true" tempdir="${build.dir}">
+                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" jvm="${platform.java}" showoutput="true" tempdir="${build.dir}">
                     <batchtest todir="${build.test.results.dir}">
                         <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
@@ -366,4 +402,7 @@
                         <path path="@{classpath}"/>
                     </classpath>
+                    <bootclasspath>
+                        <path path="${platform.bootcp}"/>
+                    </bootclasspath>
                 </nbjpdastart>
             </sequential>
@@ -381,5 +420,7 @@
     </target>
     <target name="-init-debug-args">
-        <property name="version-output" value="java version &quot;${ant.java.version}"/>
+        <exec executable="${platform.java}" outputproperty="version-output">
+            <arg value="-version"/>
+        </exec>
         <condition property="have-jdk-older-than-1.4">
             <or>
@@ -406,5 +447,5 @@
             <element name="customize" optional="true"/>
             <sequential>
-                <java classname="@{classname}" dir="${work.dir}" fork="true">
+                <java classname="@{classname}" dir="${work.dir}" fork="true" jvm="${platform.java}">
                     <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                     <jvmarg line="${debug-args-line}"/>
@@ -431,5 +472,5 @@
             <element name="customize" optional="true"/>
             <sequential>
-                <java classname="@{classname}" dir="${work.dir}" fork="true">
+                <java classname="@{classname}" dir="${work.dir}" fork="true" jvm="${platform.java}">
                     <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                     <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
@@ -613,5 +654,5 @@
             <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
         </pathconvert>
-        <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
+        <echo>${platform.java} -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
     </target>
     <target depends="init,compile,-pre-pre-jar,-pre-jar,-init-macrodef-copylibs" if="do.archive+manifest.available+main.class+mkdist.available+splashscreen.available" name="-do-jar-with-libraries-and-splashscreen">
@@ -627,5 +668,5 @@
         <echo>To run this application from the command line without Ant, try:</echo>
         <property location="${dist.jar}" name="dist.jar.resolved"/>
-        <echo>java -jar "${dist.jar.resolved}"</echo>
+        <echo>${platform.java} -jar "${dist.jar.resolved}"</echo>
     </target>
     <target depends="init,compile,-pre-pre-jar,-pre-jar,-init-macrodef-copylibs" if="do.archive+manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries" unless="splashscreen.available">
@@ -637,5 +678,5 @@
         <echo>To run this application from the command line without Ant, try:</echo>
         <property location="${dist.jar}" name="dist.jar.resolved"/>
-        <echo>java -jar "${dist.jar.resolved}"</echo>
+        <echo>${platform.java} -jar "${dist.jar.resolved}"</echo>
     </target>
     <target name="-post-jar">
@@ -715,5 +756,5 @@
     <target depends="init" if="have.sources" name="-javadoc-build">
         <mkdir dir="${dist.javadoc.dir}"/>
-        <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
+        <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" executable="${platform.javadoc}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
             <classpath>
                 <path path="${javac.classpath}"/>
Index: /trunk/fmgVen/nbproject/genfiles.properties
===================================================================
--- /trunk/fmgVen/nbproject/genfiles.properties	(revision 20)
+++ /trunk/fmgVen/nbproject/genfiles.properties	(revision 30)
@@ -1,8 +1,8 @@
-build.xml.data.CRC32=d00ffa57
+build.xml.data.CRC32=31e5c25b
 build.xml.script.CRC32=a9b2e5a3
 build.xml.stylesheet.CRC32=28e38971@1.38.1.45
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=d00ffa57
-nbproject/build-impl.xml.script.CRC32=494c2ca4
+nbproject/build-impl.xml.data.CRC32=31e5c25b
+nbproject/build-impl.xml.script.CRC32=68c11675
 nbproject/build-impl.xml.stylesheet.CRC32=78c6a6ee@1.38.1.45
Index: /trunk/fmgVen/nbproject/project.properties
===================================================================
--- /trunk/fmgVen/nbproject/project.properties	(revision 20)
+++ /trunk/fmgVen/nbproject/project.properties	(revision 30)
@@ -1,2 +1,5 @@
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.run.all.processors=true
 application.args=
 application.title=fmgVen
@@ -20,13 +23,15 @@
 dist.jar=${dist.dir}/fmgVen.jar
 dist.javadoc.dir=${dist.dir}/javadoc
+endorsed.classpath=
 excludes=
-file.reference.spring.jar=lib/spring.jar
 includes=**
 jar.compress=false
 javac.classpath=\
-    ${file.reference.spring.jar}
+    ${libs.Ven.classpath}
 # Space-separated list of extra javac options
 javac.compilerargs=
 javac.deprecation=false
+javac.processorpath=\
+    ${javac.classpath}
 javac.source=1.4
 javac.target=1.4
@@ -34,5 +39,6 @@
     ${javac.classpath}:\
     ${build.classes.dir}:\
-    ${libs.junit.classpath}
+    ${libs.junit.classpath}:\
+    ${libs.Test.classpath}
 javadoc.additionalparam=
 javadoc.author=false
@@ -47,5 +53,5 @@
 javadoc.windowtitle=
 meta.inf.dir=${src.dir}/META-INF
-platform.active=default_platform
+platform.active=JDK_1.4
 run.classpath=\
     ${javac.classpath}:\
@@ -57,5 +63,8 @@
 run.test.classpath=\
     ${javac.test.classpath}:\
-    ${build.test.classes.dir}
+    ${build.test.classes.dir}:\
+    ${libs.Test.classpath}
+source.encoding=UTF-8
 src.dir=src
 test.src.dir=test
+project.license=ven-apache20
Index: /trunk/fmgVen/nbproject/project.xml
===================================================================
--- /trunk/fmgVen/nbproject/project.xml	(revision 20)
+++ /trunk/fmgVen/nbproject/project.xml	(revision 30)
@@ -6,4 +6,5 @@
             <name>fmgVen</name>
             <minimum-ant-version>1.6.5</minimum-ant-version>
+            <explicit-platform explicit-source-supported="true"/>
             <source-roots>
                 <root id="src.dir"/>
@@ -16,4 +17,8 @@
             <definitions>.\lib\nblibraries.properties</definitions>
         </libraries>
+        <spring-data xmlns="http://www.netbeans.org/ns/spring-data/1">
+            <config-files/>
+            <config-file-groups/>
+        </spring-data>
     </configuration>
 </project>
Index: /trunk/fmgVen/src/com/fmguler/ven/Criteria.java
===================================================================
--- /trunk/fmgVen/src/com/fmguler/ven/Criteria.java	(revision 30)
+++ /trunk/fmgVen/src/com/fmguler/ven/Criteria.java	(revision 30)
@@ -0,0 +1,343 @@
+/*
+ *  fmgVen - A Convention over Configuration Java ORM Tool
+ *  Copyright 2011 Fatih Mehmet Güler
+ * 
+ *  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.
+ *  under the License.
+ */
+package com.fmguler.ven;
+
+import com.fmguler.ven.util.Convert;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Stack;
+
+/**
+ * Criteria object, used to filter the result of a query according to some criteria.
+ * <p>
+ * Can be used in two modes; as string criteria or typed criteria.
+ * The string criteria is used like;
+ * <pre>
+ * new Criteria().add("and SomeDomainObject.anotherDomainObjects.name like :p1").param("p1", "a%");
+ * </pre>
+ * And the typed criteria is used like;
+ * <pre>
+ * new Criteria().eq(attr,value).like(attr,value).and().gt(attr, value).or().orderAsc(attr).orderDesc(attr).limit(limit, offset);
+ * </pre>
+ *
+ * This criteria object is used to filter SQL results by adding the "Criteria.criteriaToSQL()" output to the where clause.
+ * 
+ * @author Fatih Mehmet Güler
+ */
+public class Criteria {
+    private StringBuffer criteriaStringBuffer = new StringBuffer(); //for string criteria
+    private LinkedList criterionList = new LinkedList(); //for typed criteria
+    private Map parameters = new HashMap(); //the parameters used in criteria string
+    private int limit = 20;
+    private int offset = 0;
+    int paramCount = 0;
+
+    //--------------------------------------------------------------------------
+    //String Criteria Methods
+    /**
+     * Add a criteria string
+     */
+    public Criteria add(String criteriaString) {
+        this.criteriaStringBuffer.append(" ").append(criteriaString);
+        return this;
+    }
+
+    /**
+     * Add the parameter used in criteria string
+     */
+    public Criteria param(String parameter, Object value) {
+        this.parameters.put(parameter, value);
+        return this;
+    }
+
+    /**
+     * Converts criteria string to SQL
+     * @return the criteria string as SQL where clause
+     */
+    public String criteriaStringToSQL() {
+        StringBuffer resultBuffer = new StringBuffer();
+        String criteriaString = criteriaStringBuffer.toString();
+        criteriaString = criteriaString.replaceAll("\\(", "\\( ");
+        criteriaString = criteriaString.replaceAll("\\)", " \\)");
+
+        String[] parts = criteriaString.split(" ");
+        for (int i = 0; i < parts.length; i++) {
+            if (!parts[i].startsWith(":") && parts[i].indexOf(".") >= 0) {
+                int lastDot = parts[i].lastIndexOf('.');
+                resultBuffer.append(" ");
+                int u = parts[i].length();
+                resultBuffer.append(Convert.toDB(parts[i].substring(0, lastDot).replace('.', '_')));
+                resultBuffer.append(Convert.toDB(parts[i].substring(lastDot, u)));
+            } else {
+                resultBuffer.append(" ").append(parts[i]);
+            }
+        }
+        return resultBuffer.toString();
+    }
+
+    /**
+     * @return the parameter map
+     */
+    public Map getParameters() {
+        return parameters;
+    }
+
+    //--------------------------------------------------------------------------
+    //Typed Criteria Methods
+    /**
+     * Add a criterion where an attribue equals a value (SQL = operator)
+     */
+    public Criteria eq(String attribute, String value) {
+        criterionList.add(new Criterion(attribute, Criterion.OP_EQUALS, value));
+        return this;
+    }
+
+    /**
+     * Add a criterion where an attribue is like a value (SQL like operator)
+     */
+    public Criteria like(String attribute, String value) {
+        criterionList.add(new Criterion(attribute, Criterion.OP_LIKE, value));
+        return this;
+    }
+
+    /**
+     * Add a criterion where an attribue is similar to a value (SQL similar to operator)
+     */
+    public Criteria similarto(String attribute, String value) {
+        criterionList.add(new Criterion(attribute, Criterion.OP_SIMILAR_TO, value));
+        return this;
+    }
+
+    /**
+     * Add a criterion where an attribue is greater than a value (SQL > operator)
+     */
+    public Criteria gt(String attribute, String value) {
+        criterionList.add(new Criterion(attribute, Criterion.OP_GREATER_THAN, value));
+        return this;
+    }
+
+    /**
+     * Add a criterion where an attribue is less than a value (SQL < operator)
+     */
+    public Criteria lt(String attribute, String value) {
+        criterionList.add(new Criterion(attribute, Criterion.OP_LESS_THAN, value));
+        return this;
+    }
+
+    /**
+     * Add a criterion where an attribue is null (SQL is null operator)
+     */
+    public Criteria isNull(String attribute) {
+        criterionList.add(new Criterion(attribute, Criterion.OP_ISNULL, null));
+        return this;
+    }
+
+    /**
+     * Add: order by attribute asc
+     */
+    public Criteria orderAsc(String attribute) {
+        //Not implemented yet.
+        return this;
+    }
+
+    /**
+     * Add: order by attribute desc
+     */
+    public Criteria orderDesc(String attribute) {
+        //Not implemented yet.
+        return this;
+    }
+
+    /**
+     * Add limit and offset to the clause
+     */
+    public Criteria limit(int limit, int offset) {
+        this.limit = limit;
+        this.offset = offset;
+        return this;
+    }
+
+    //--------------------------------------------------------------------------
+    //Connectives
+    /**
+     * Connect previous two criteria with logical and
+     * (as in postfix notation)
+     */
+    public Criteria and() {
+        criterionList.add(new Criterion(Criterion.CONN_AND));
+        return this;
+    }
+
+    /**
+     * Connect previous two criteria with logical or
+     * (as in postfix notation)
+     */
+    public Criteria or() {
+        criterionList.add(new Criterion(Criterion.CONN_OR));
+        return this;
+    }
+
+    /**
+     * Connect previous criterion with logical not
+     * (as in postfix notation)
+     */
+    public Criteria not() {
+        criterionList.add(new Criterion(Criterion.CONN_NOT));
+        return this;
+    }
+
+    /**
+     * Converts typed criteria to SQL
+     * @return the typed criteria as SQL where clause
+     */
+    public String criteriaToSQL() {
+        LinkedList clone = (LinkedList)criterionList.clone();
+        Stack stack = new Stack();
+        while (!clone.isEmpty()) {
+            Criterion criterion = (Criterion)clone.removeFirst();
+            if (!criterion.isConnective()) {
+                String s = "(" + convertOperatorToSQL(criterion) + ")";
+                stack.push(s);
+            } else {
+                String conn = criterion.connective;
+                if (conn.equals(Criterion.CONN_AND)) {
+                    String s1 = (String)stack.pop();
+                    String s2 = (String)stack.pop();
+                    String sr = "(" + s1 + " and " + s2 + ")";
+                    stack.push(sr);
+                } else if (conn.equals(Criterion.CONN_OR)) {
+                        String s1 = (String)stack.pop();
+                        String s2 = (String)stack.pop();
+                        String sr = "(" + s1 + " or " + s2 + ")";
+                        stack.push(sr);
+                    } else if (conn.equals(Criterion.CONN_NOT)) {
+                            String s = (String)stack.pop();
+                            String sr = "not (" + s + ")";
+                            stack.push(sr);
+                        }
+            }
+        }
+
+        if (stack.isEmpty()) return "1=1";
+
+        String result = (String)stack.pop();
+        return result;
+    }
+
+    //convert the attribute-operator-value criterion to SQL
+    private String convertOperatorToSQL(Criterion criterion) {
+        String attribute = convertAttributeToAlias(criterion.attribute);
+        String operator = criterion.operator;
+        Object value = criterion.value;
+        String result = "";
+
+        if (value == null) {
+            //no value e.g. is null operator
+            result = attribute + " " + operator;
+        } else {
+            String paramName = genParamName();
+            parameters.put(paramName, value);
+            result = attribute + " " + operator + " :" + paramName + "";
+        }
+
+        return result;
+    }
+
+    //convert attribute to SQL alias
+    protected String convertAttributeToAlias(String attribute) {
+        //we convert like: x.y.z.t to x_y_z.t
+        StringBuffer resultBuffer = new StringBuffer();
+        int lastDot = attribute.lastIndexOf('.');
+        resultBuffer.append(" ");
+        int u = attribute.length();
+        resultBuffer.append(Convert.toDB(attribute.substring(0, lastDot).replace('.', '_')));
+        resultBuffer.append(Convert.toDB(attribute.substring(lastDot, u)));
+        return resultBuffer.toString();
+    }
+
+    //generate parameter for typed criteria
+    private String genParamName() {
+        return "__p" + paramCount++;
+    }
+
+    //test the criteria object
+    public static void main(String[] args) {
+        Criteria criteria = new Criteria() //criteria object
+                .like("SomeDomainObject.anotherDomainObjects.name", "a%") //attribute like value
+                .eq("SomeDomainObject.name", "sdo1") //attribute equals value
+                .and() //connect previous criteria with and
+                .isNull("SomeDomainObject.description") //attribute is null
+                .or(); //connect previous criteria with and
+
+        //print the resulting where clause SQL
+        System.out.println(criteria.criteriaToSQL());
+
+        //the result is;
+        //(( some_domain_object.description is null) or (( some_domain_object.name = :__p1) and ( some_domain_object_another_domain_objects.name like :__p0)))
+    }
+}
+
+/**
+ * Each criterion used in the criteria.
+ * Used to hold attribute-operator-value triplet.
+ * Used internally.
+ * @author Fatih Mehmet Güler
+ */
+class Criterion {
+    //available logical connectives
+    public static final String CONN_AND = "and";
+    public static final String CONN_OR = "or";
+    public static final String CONN_NOT = "not";
+    //available operators
+    public static final String OP_EQUALS = "=";
+    public static final String OP_LESS_THAN = "<";
+    public static final String OP_GREATER_THAN = ">";
+    public static final String OP_LIKE = "like";
+    public static final String OP_SIMILAR_TO = "similar to";
+    public static final String OP_NOT = "not";
+    public static final String OP_ISNULL = "is null";
+    //attribute-operator-value triplet
+    public String attribute;
+    public String operator;
+    public Object value;
+    //logical connective
+    public String connective = null;
+
+    public Criterion(String attribute, String operator, Object value) {
+        this.attribute = attribute;
+        this.operator = operator;
+        this.value = value;
+    }
+
+    public Criterion(String connective) {
+        this.connective = connective;
+    }
+
+    public boolean isConnective() {
+        return connective != null;
+    }
+
+    /**
+     * @return string representation of this criterion
+     */
+    public String toString() {
+        if (isConnective()) return connective;
+        return attribute + " " + operator + " " + value;
+    }
+}
Index: /trunk/fmgVen/src/com/fmguler/ven/QueryGenerator.java
===================================================================
--- /trunk/fmgVen/src/com/fmguler/ven/QueryGenerator.java	(revision 30)
+++ /trunk/fmgVen/src/com/fmguler/ven/QueryGenerator.java	(revision 30)
@@ -0,0 +1,239 @@
+/*
+ *  fmgVen - A Convention over Configuration Java ORM Tool
+ *  Copyright 2010 Fatih Mehmet Güler
+ * 
+ *  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.
+ *  under the License.
+ */
+package com.fmguler.ven;
+
+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;
+import org.springframework.beans.BeanWrapperImpl;
+
+/**
+ * Generates queries in the form of 'Convention over Configuration' for the specified objects.
+ * @author Fatih Mehmet Güler
+ */
+public class QueryGenerator {
+    private Set domainPackages;
+    private Set dbClasses;
+    private boolean debug = true;
+
+    public QueryGenerator() {
+        domainPackages = new HashSet();
+        dbClasses = new HashSet();
+        //the predefined database classes;
+        this.dbClasses.add(Integer.class);
+        this.dbClasses.add(String.class);
+        this.dbClasses.add(Date.class);
+        this.dbClasses.add(Double.class);
+        this.dbClasses.add(Boolean.class);
+    }
+
+    /**
+     * 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();
+    }
+
+    public String generateCountQuery() {
+        return null;
+    }
+
+    /**
+     * Generates insert query for the specified object
+     * @param object the object to generate insert query for
+     * @return the insert SQL query
+     */
+    public String generateInsertQuery(Object object) {
+        BeanWrapper wr = new BeanWrapperImpl(object);
+        String objectName = Convert.toSimpleName(object.getClass().getName());
+        String tableName = Convert.toDB(objectName);
+        PropertyDescriptor[] pdArr = wr.getPropertyDescriptors();
+
+        //generate insert query
+        StringBuffer query = new StringBuffer("insert into " + tableName + "(");
+        StringBuffer values = new StringBuffer(" values(");
+        for (int i = 0; i < pdArr.length; i++) {
+            Class fieldClass = pdArr[i].getPropertyType(); //field class
+            String columnName = Convert.toDB(pdArr[i].getName()); //column name
+            String fieldName = pdArr[i].getName(); //field name
+            //if (fieldName.equals("id")) continue; //remove if it does not break the sequence
+            if (dbClasses.contains(fieldClass)) { //direct database field (Integer,String,Date, etc)
+                query.append(columnName);
+                query.append(",");
+                values.append(":").append(fieldName);
+                values.append(",");
+            }
+            if (fieldClass.getPackage() != null && domainPackages.contains(fieldClass.getPackage().getName())) { //object
+                query.append(Convert.toDB(fieldName)).append("_id");
+                query.append(",");
+                values.append(":").append(fieldName).append(".id");
+                values.append(",");
+            }
+        }
+        query.deleteCharAt(query.length() - 1);
+        query.append(")");
+        values.deleteCharAt(values.length() - 1);
+        values.append(");");
+        query.append(values);
+
+        return query.toString();
+    }
+
+    /**
+     * Generates update query for the specified object
+     * @param object the object to generate update query for
+     * @return the update SQL query
+     */
+    public String generateUpdateQuery(Object object) throws VenException {
+        BeanWrapper wr = new BeanWrapperImpl(object);
+        String objectName = Convert.toSimpleName(object.getClass().getName());
+        String tableName = Convert.toDB(objectName);
+        PropertyDescriptor[] pdArr = wr.getPropertyDescriptors();
+
+        StringBuffer query = new StringBuffer("update " + tableName + " set ");
+        for (int i = 0; i < pdArr.length; i++) {
+            Class fieldClass = pdArr[i].getPropertyType(); //field class
+            String columnName = Convert.toDB(pdArr[i].getName()); //column name
+            String fieldName = pdArr[i].getName(); //field name
+            if (dbClasses.contains(fieldClass)) { //direct database field (Integer,String,Date, etc)
+                query.append(columnName).append("=:").append(fieldName);
+                query.append(",");
+            }
+            if (fieldClass.getPackage() != null && domainPackages.contains(fieldClass.getPackage().getName())) { //object
+                query.append(columnName).append("_id=:").append(fieldName).append(".id");
+                query.append(",");
+            }
+        }
+        query.deleteCharAt(query.length() - 1);
+        query.append(" where id = :id ;");
+        return query.toString();
+    }
+
+    /**
+     * Generates delete query for the specified object class
+     * @param objectClass the object class to generate query for
+     * @return the delete SQL query
+     */
+    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
+     * @param object the objectc to generate sequence query for
+     * @return the SQL query to select next id
+     */
+    public String generateSequenceQuery(Object object) throws VenException {
+        String objectName = Convert.toSimpleName(object.getClass().getName());
+        String tableName = Convert.toDB(objectName);
+        return "select nextval('" + tableName + "_id_seq');";
+    }
+
+    //--------------------------------------------------------------------------
+    //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);
+    }
+}
Index: /trunk/fmgVen/src/com/fmguler/ven/QueryMapper.java
===================================================================
--- /trunk/fmgVen/src/com/fmguler/ven/QueryMapper.java	(revision 30)
+++ /trunk/fmgVen/src/com/fmguler/ven/QueryMapper.java	(revision 30)
@@ -0,0 +1,193 @@
+/*
+ *  fmgVen - A Convention over Configuration Java ORM Tool
+ *  Copyright 2010 Fatih Mehmet Güler
+ * 
+ *  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.
+ *  under the License.
+ */
+package com.fmguler.ven;
+
+import com.fmguler.ven.util.Convert;
+import com.fmguler.ven.util.VenList;
+import java.beans.PropertyDescriptor;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.sql.DataSource;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.jdbc.core.RowCallbackHandler;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+
+/**
+ * Maps the result of the query generated in the form of 'Convention over Configuration' to the specified object.
+ * @author Fatih Mehmet Güler
+ */
+public class QueryMapper {
+    private NamedParameterJdbcTemplate template;
+    private Set domainPackages;
+    private Set dbClasses;
+    private boolean debug = true;
+
+    public QueryMapper() {
+        domainPackages = new HashSet();
+        dbClasses = new HashSet();
+        //the predefined database classes;
+        this.dbClasses.add(Integer.class);
+        this.dbClasses.add(String.class);
+        this.dbClasses.add(Date.class);
+        this.dbClasses.add(Double.class);
+        this.dbClasses.add(Boolean.class);
+    }
+
+    /**
+     * Executes the specified query setting the specified parameters,
+     * and maps the results to the instances of the specified objectClass.
+     * @param query select SQL query in the conventional format
+     * @param parameters named query parameter values
+     * @param objectClass the type of the object to be mapped
+     * @return the list of mapped objects
+     */
+    public List list(String query, Map parameters, final Class objectClass) {
+        long t1 = System.currentTimeMillis();
+        final List results = new LinkedList();
+        final String tableName = Convert.toDB(Convert.toSimpleName(objectClass.getName()));
+        final Set columns = new HashSet();
+
+        template.query(query, parameters, new RowCallbackHandler() {
+            public void processRow(ResultSet rs) throws SQLException {
+                enumerateColumns(columns, rs);
+                mapRecursively(rs, columns, tableName, objectClass, results);
+            }
+        });
+
+        System.out.println("Ven - list time = " + (System.currentTimeMillis() - t1));
+        return results;
+    }
+
+    //--------------------------------------------------------------------------
+    //PRIVATE METHODS
+    //recursively map the resultSet to the object and add to the list
+    protected void mapRecursively(ResultSet rs, Set columns, String tableName, Class objectClass, List parentList) {
+        try {
+            if (!columns.contains(tableName + "_id")) return; //this object does not exist in the columns
+            Object id = rs.getObject(tableName + "_id");
+            if (id == null) return; //this object exists in the columns but null, probably because of left join
+
+            //create bean wrapper for the object class
+            BeanWrapper wr = new BeanWrapperImpl(objectClass); //already caches class introspection (CachedIntrospectionResults.forClass())
+            wr.setPropertyValue("id", id); //set the id property
+            Object object = wr.getWrappedInstance();
+            boolean map = true;
+
+            //check if this object exists in the parent list (since SQL joins are cartesian products, do not create new object if this row is just the same as previous)
+            for (Iterator it = parentList.iterator(); it.hasNext();) {
+                Object objectInList = (Object)it.next();
+                if (objectIdEquals(objectInList, id)) {
+                    wr.setWrappedInstance(objectInList); //already exists in the list, use that instance
+                    map = false; // and do not map again
+                    break;
+                }
+            }
+            if (map) parentList.add(object); //could not find in the parent list, add the new object
+
+            PropertyDescriptor[] pdArr = wr.getPropertyDescriptors();
+            for (int i = 0; i < pdArr.length; i++) {
+                PropertyDescriptor pd = pdArr[i];
+                Class fieldClass = pd.getPropertyType(); //field class
+                String fieldName = Convert.toDB(pd.getName()); //field name
+                Object fieldValue = wr.getPropertyValue(pd.getName());
+                String columnName = tableName + "_" + fieldName;
+
+                //database class (primitive property)
+                if (map && dbClasses.contains(fieldClass)) {
+                    if (columns.contains(columnName)) {
+                        if (debug) System.out.println(">>field is found: " + columnName);
+                        wr.setPropertyValue(pd.getName(), rs.getObject(columnName));
+                    } else {
+                        if (debug) System.out.println("--field not found: " + columnName);
+                    }
+                }
+
+                //many to one association (object property)
+                if (map && fieldClass.getPackage() != null && domainPackages.contains(fieldClass.getPackage().getName())) {
+                    if (columns.contains(columnName + "_id")) {
+                        if (debug) System.out.println(">>object is found " + columnName);
+                        List list = new ArrayList(1); //we know there will be single result
+                        mapRecursively(rs, columns, columnName, fieldClass, list);
+                        if (list.size() > 0) wr.setPropertyValue(pd.getName(), list.get(0));
+                    } else {
+                        if (debug) System.out.println("--object not found: " + columnName);
+                    }
+                }
+
+                //one to many association (list property)
+                if (fieldValue instanceof List) { //Note: here recurring row's list property is mapped and add to parent's list
+                    if (columns.contains(columnName + "_id")) {
+                        Class elementClass = VenList.findElementClass((List)fieldValue);
+                        if (debug) System.out.println(">>list is found " + columnName);
+                        mapRecursively(rs, columns, columnName, elementClass, (List)fieldValue);
+                    } else {
+                        if (debug) System.out.println("--list not found: " + columnName);
+                    }
+                }
+            }
+        } catch (Exception ex) {
+            if (debug) {
+                System.out.println("Ven - error while mapping row; ");
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    //enumerate columns from the resultset
+    private void enumerateColumns(Set columns, ResultSet rs) throws SQLException {
+        if (!columns.isEmpty()) return;
+        for (int i = 1; i < rs.getMetaData().getColumnCount() + 1; i++) {
+            columns.add(rs.getMetaData().getColumnName(i));
+        }
+    }
+
+    //check if the specified objects are the same entity (according to id fields)
+    private boolean objectIdEquals(Object object, Object id) {
+        //return obj1.equals(obj2); //objects need to implement equals()
+        //TODO: more efficient (invoke getId method)
+        BeanWrapper wr = new BeanWrapperImpl(object);
+        return id.equals(wr.getPropertyValue("id"));
+    }
+
+    //--------------------------------------------------------------------------
+    //SETTERS
+    /**
+     * @param dataSource used for accessing database
+     */
+    public void setDataSource(DataSource dataSource) {
+        if (dataSource == null) throw new RuntimeException("fmgVen - DataSource cannot be null");
+        this.template = new NamedParameterJdbcTemplate(dataSource);
+    }
+
+    /**
+     * Add the domain packages that will be considered persistent
+     * @param domainPackage the domain package
+     */
+    public void addDomainPackage(String domainPackage) {
+        domainPackages.add(domainPackage);
+    }
+}
Index: /trunk/fmgVen/src/com/fmguler/ven/Ven.java
===================================================================
--- /trunk/fmgVen/src/com/fmguler/ven/Ven.java	(revision 30)
+++ /trunk/fmgVen/src/com/fmguler/ven/Ven.java	(revision 30)
@@ -0,0 +1,198 @@
+/*
+ *  fmgVen - A Convention over Configuration Java ORM Tool
+ *  Copyright 2010 Fatih Mehmet Güler
+ * 
+ *  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.
+ *  under the License.
+ */
+package com.fmguler.ven;
+
+import com.fmguler.ven.util.Convert;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.sql.DataSource;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.core.namedparam.SqlParameterSource;
+
+/**
+ * The main class for data access
+ * @author Fatih Mehmet Güler
+ */
+public class Ven {
+    private NamedParameterJdbcTemplate template;
+    private QueryGenerator generator;
+    private QueryMapper mapper;
+    private boolean debug = true;
+
+    public Ven() {
+        generator = new QueryGenerator();
+        mapper = new QueryMapper();
+    }
+
+    public int count() {
+        return 0;
+    }
+
+    /**
+     * Get the object with the specified id, of the specified objectClass type.
+     * <p>
+     * By default none of the associations will be retrieved.
+     * To include the object associations (retrieve the object graph) joins should be specified, e.g.
+     * <code>SomeObject.anotherObject</code>
+     * 
+     * @param id the id of the object to be retrieved
+     * @param objectClass the class of the object to be retrieved
+     * @param joins the set of object graphs to be included with the object
+     * @return the retrieved object including specified associations
+     */
+    public Object get(int id, Class objectClass, Set joins) {
+        String query = generator.generateSelectQuery(objectClass, joins);
+        query += " where 1=1 and " + Convert.toDB(Convert.toSimpleName(objectClass.getName())) + ".id = :___id ";
+
+        Map paramMap = new HashMap();
+        paramMap.put("___id", new Integer(id));
+        if (debug) System.out.println("Ven - SQL: " + query);
+
+        List result = mapper.list(query, paramMap, objectClass);
+        if (result.isEmpty()) return null;
+        if (result.size() > 1) System.out.println("Ven - WARNING >> get(id) returns more than one row");
+        return result.get(0);
+    }
+
+    /**
+     * List the objects of the specified objectClass type.
+     * <p>
+     * By default none of the associations will be retrieved.
+     * To include the object associations (retrieve the object graph) joins should be specified, e.g.
+     * <code>SomeObject.anotherObject</code>
+     * 
+     * @param objectClass the class of the objects to be retrieved
+     * @param joins the set of object graphs to be included with objects
+     * @return the list of objects including specified associations
+     */
+    public List list(Class objectClass, Set joins) {
+        String query = generator.generateSelectQuery(objectClass, joins);
+
+        Map paramMap = new HashMap();
+        if (debug) System.out.println("Ven - SQL: " + query);
+
+        List result = mapper.list(query, paramMap, objectClass);
+        return result;
+    }
+
+    /**
+     * List the objects of the specified objectClass type, filtering according to some criteria.
+     * <p>
+     * By default none of the associations will be retrieved.
+     * To include the object associations (retrieve the object graph) joins should be specified, e.g.
+     * <code>SomeObject.anotherObject</code>
+     * 
+     * @param objectClass the class of the objects to be retrieved
+     * @param joins the set of object graphs to be included with objects
+     * @param criteria to filter and order the result according to some criteria
+     * @return the list of objects including the specified associations filtered according to the specified criteria
+     */
+    public List list(Class objectClass, Set joins, Criteria criteria) {
+        String query = generator.generateSelectQuery(objectClass, joins);
+        query += " where 1=1 " + criteria.criteriaStringToSQL() + " and " + criteria.criteriaToSQL();
+
+        if (debug) System.out.println("Ven - SQL: " + query);
+
+        List result = mapper.list(query, criteria.getParameters(), objectClass);
+        return result;
+    }
+
+    /**
+     * Save the object. If it has a non null (or non zero) "id" property it will be updated.
+     * It will be inserted otherwise.
+     * <p>
+     * The object will be saved to a table with the same name as the object,
+     * The fields of object will be mapped to the table fields.
+     * 
+     * @param object the object to be saved
+     */
+    public void save(Object object) {
+        String query = null;
+
+        if (isObjectNew(object)) {
+            //if this is a new object assign a new id first
+            generateId(object);
+            query = generator.generateInsertQuery(object);
+        } else {
+            query = generator.generateUpdateQuery(object);
+        }
+
+        //execute the insert/update query
+        SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(object);
+        template.update(query, parameterSource);
+    }
+
+    /**
+     * Delete the the object with the specified id of the specified objectClass type
+     * @param id the id of the object to be deleted
+     * @param objectClass the class of the object to be deleted
+     */
+    public void delete(int id, Class objectClass) {
+        String query = generator.generateDeleteQuery(objectClass);
+        Map parameterMap = new HashMap();
+        parameterMap.put("id", new Integer(id));
+        template.update(query, parameterMap);
+    }
+
+    //--------------------------------------------------------------------------
+    //PRIVATE METHODS
+    //return true if the object id is zero or null false otherwise
+    private boolean isObjectNew(Object object) throws VenException {
+        BeanWrapper beanWrapper = new BeanWrapperImpl(object);
+        Object objectId = beanWrapper.getPropertyValue("id");
+        if (objectId == null) return true;
+        if (!(objectId instanceof Integer)) throw new VenException(VenException.EC_GENERATOR_OBJECT_ID_TYPE_INVALID);
+        return ((Integer)objectId).intValue() == 0;
+    }
+
+    //set new object id
+    private void generateId(Object object) {
+        Integer newObjectId = new Integer(template.queryForInt(generator.generateSequenceQuery(object), new HashMap()));
+        BeanWrapper beanWrapper = new BeanWrapperImpl(object);
+        beanWrapper.setPropertyValue("id", newObjectId);
+    }
+
+    //--------------------------------------------------------------------------
+    //SETTERS
+    /**
+     * Set the DataSource to be used to access to the database
+     */
+    public void setDataSource(DataSource dataSource) {
+        if (dataSource == null) throw new RuntimeException("fmgVen - DataSource cannot be null");
+        this.template = new NamedParameterJdbcTemplate(dataSource);
+        mapper.setDataSource(dataSource);
+    }
+
+    /**
+     * Add the domain packages that have corresponding database tables.
+     * <p>
+     * The objects in these packages are considered persistable.
+     * @param domainPackage the package of the entity classes.
+     * @return this instance to allow chaining.
+     */
+    public Ven addDomainPackage(String domainPackage) {
+        generator.addDomainPackage(domainPackage);
+        mapper.addDomainPackage(domainPackage);
+        return this;
+    }
+}
Index: /trunk/fmgVen/src/com/fmguler/ven/VenException.java
===================================================================
--- /trunk/fmgVen/src/com/fmguler/ven/VenException.java	(revision 30)
+++ /trunk/fmgVen/src/com/fmguler/ven/VenException.java	(revision 30)
@@ -0,0 +1,74 @@
+/*
+ *  fmgVen - A Convention over Configuration Java ORM Tool
+ *  Copyright 2010 Fatih Mehmet Güler
+ * 
+ *  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.
+ *  under the License.
+ */
+package com.fmguler.ven;
+
+/**
+ * All kinds of exceptions in Ven operations.
+ * @author Fatih Mehmet Güler
+ */
+public class VenException extends RuntimeException {
+    private String errorCode;
+    private String errorParam;
+    //Error codes
+    //"Invalid object, \"id\" property must be of integer type"
+    public static final String EC_GENERATOR_OBJECT_ID_TYPE_INVALID = "ec-generator-object-id-type-invalid";
+
+    /**
+     * Init VenException with an error code
+     * @param errorCode the error code
+     */
+    public VenException(String errorCode) {
+        this.errorCode = errorCode;
+    }
+
+    /**
+     * Init VenException with an error code and an error parameter
+     * @param errorCode the error code
+     * @param errorParam the error param
+     */
+    public VenException(String errorCode, String errorParam) {
+        this.errorCode = errorCode;
+        this.errorParam = errorParam;
+    }
+
+    /**
+     * Init VenException with an error code, error parameter and the cause of the exception
+     * @param errorCode the error code
+     * @param errorParam the error parameter
+     * @param cause the cause of the exception
+     */
+    public VenException(String errorCode, String errorParam, Throwable cause) {
+        super(cause);
+        this.errorCode = errorCode;
+        this.errorParam = errorParam;
+    }
+
+    /**
+     * @return the error code of the exception
+     */
+    public String getErrorCode() {
+        return errorCode;
+    }
+
+    /**
+     * @return the error parameter of the exception, which can contain details about the error
+     */
+    public String getErrorParam() {
+        return errorParam;
+    }
+}
Index: /trunk/fmgVen/src/com/fmguler/ven/util/Convert.java
===================================================================
--- /trunk/fmgVen/src/com/fmguler/ven/util/Convert.java	(revision 30)
+++ /trunk/fmgVen/src/com/fmguler/ven/util/Convert.java	(revision 30)
@@ -0,0 +1,61 @@
+/*
+ *  fmgVen - A Convention over Configuration Java ORM Tool
+ *  Copyright 2010 Fatih Mehmet Güler
+ * 
+ *  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.
+ *  under the License.
+ */
+package com.fmguler.ven.util;
+
+import java.util.Locale;
+
+/**
+ * Utility class for conversions from database naming convention to java, and vice versa
+ * @author Fatih Mehmet Güler
+ */
+public class Convert {
+    /**
+     * Convert from java camelCase case to database naming convention
+     * <p>
+     * For example, if the name of the given name is SomeDomainObject
+     * it will be converted to some_domain_object
+     *
+     * @param camelCase the camelCase case name
+     * @return database style name
+     */
+    public static String toDB(String camelCase) {
+        if (camelCase.equals("")) return "";
+        StringBuffer result = new StringBuffer();
+        result.append(camelCase.substring(0, 1).toLowerCase(Locale.ENGLISH));
+        for (int i = 1; i < camelCase.length(); i++) {
+            String sCamel = camelCase.substring(i, i + 1);
+            String sLower = sCamel.toLowerCase(Locale.ENGLISH);
+            if (!sCamel.equals(sLower)) {
+                result.append("_").append(sLower);
+            } else result.append(sCamel);
+        }
+        return result.toString();
+    }
+
+    /**
+     * Convert the full package name to simple name.
+     * For Java 1.4 compatibility of Class.getSimpleName()
+     * @param fullName Class.getName()
+     * @return the part after the last .
+     */
+    public static String toSimpleName(String fullName) {
+        int i = fullName.lastIndexOf(".");
+        if (i < 0) return fullName;
+        return fullName.substring(i + 1);
+    }
+}
Index: /trunk/fmgVen/src/com/fmguler/ven/util/VenList.java
===================================================================
--- /trunk/fmgVen/src/com/fmguler/ven/util/VenList.java	(revision 30)
+++ /trunk/fmgVen/src/com/fmguler/ven/util/VenList.java	(revision 30)
@@ -0,0 +1,88 @@
+/*
+ *  fmgVen - A Convention over Configuration Java ORM Tool
+ *  Copyright 2011 Fatih Mehmet Güler
+ * 
+ *  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.
+ *  under the License.
+ */
+package com.fmguler.ven.util;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A Simple Linked List which informs the type of its elements.
+ * @author Fatih Mehmet Güler
+ */
+public class VenList extends LinkedList {
+    private Class elementClass;
+    private String joinField;
+
+    /**
+     * Creates new instance of VenList
+     */
+    public VenList() {
+    }
+
+    /**
+     * Creates new instance of VenList, specifying the type of elements
+     * @param elementClass the type of elements of this list
+     */
+    public VenList(Class elementClass) {
+        this.elementClass = elementClass;
+    }
+
+    /**
+     * Creates new instance of VenList, specifying the type of elements and the join field
+     * @param elementClass the type of elements of this list
+     * @param joinField the field which refers to the parent object
+     */
+    public VenList(Class elementClass, String joinField) {
+        this.elementClass = elementClass;
+        this.joinField = joinField;
+    }
+
+    /**
+     * Returns the type of the elements in this list.
+     * @return element type
+     */
+    public Class getElementClass() {
+        return elementClass;
+    }
+
+    /**
+     * Returns the field in the element class which refers the parent object
+     * @return element join field
+     */
+    public String getJoinField() {
+        return joinField;
+    }
+
+    /**
+     * Return the class of the elements in the list
+     * @param list the list
+     * @return the element class in the list
+     */
+    public static Class findElementClass(List list) {
+        if (list.size() > 0) {
+            Object elem = list.get(0);
+            return elem.getClass();
+        }
+        if (list instanceof VenList) {
+            return ((VenList)list).getElementClass();
+        } else {
+            //find according to 1.5 generic or some convention (e.g. xyzList -> xyz)
+            return null;
+        }
+    }
+}
Index: /trunk/fmgVen/src/net/fmg/ven/Olcut.java
===================================================================
--- /trunk/fmgVen/src/net/fmg/ven/Olcut.java	(revision 20)
+++ /trunk/fmgVen/src/net/fmg/ven/Olcut.java	(revision 30)
@@ -3,9 +3,8 @@
  *
  * Created on December 20, 2006, 1:45 PM
- * (4.12.06 tarihli SpringDaoDeneme çalýþmasýndan derlenmiþtir)
+ * (4.12.06 tarihli SpringDaoDeneme çalışmasından derlenmiştir)
  *
- * Ven - Ayar Yerine Gelenek veritabaný eriþim nesnesi
+ * Ven - Ayar Yerine Gelenek veritabanı erişim nesnesi
  */
-
 package net.fmg.ven;
 
@@ -18,5 +17,5 @@
 
 /**
- * Ven için ölçütlerin belirlenebileceði sýnýf
+ * Ven için ölçütlerin belirlenebileceği sınıf
  * @author Fatih Mehmet Güler
  */
@@ -25,5 +24,5 @@
     private Map parametreler;
     private Set baglaclar;
-    
+
     /** 
      * Yeni ölçüt
@@ -32,81 +31,80 @@
         this.metin = "";
         this.parametreler = new HashMap();
-        this.baglaclar =  new HashSet();
+        this.baglaclar = new HashSet();
         //{"and", "or", "=", "<>", "<", ">"}
     }
-    
+
     /**
      * YAPILMADI
      */
-    public Olcut ekle(Olcut olcut){        
+    public Olcut ekle(Olcut olcut) {
         return null;
     }
-    
+
     /**
      * YAPILMADI
      */
-    public Olcut ekle(List olcutler){        
+    public Olcut ekle(List olcutler) {
         return null;
     }
-    
+
     /**
      * YAPILMADI
      */
-    public Olcut ve(){
+    public Olcut ve() {
         return null;
     }
-    
+
     /**
-     * koþul ekle
+     * koşul ekle
      */
-    public Olcut ekle(String kosul){
-        this.metin +=" "+kosul;
+    public Olcut ekle(String kosul) {
+        this.metin += " " + kosul;
         return this;
     }
-    
+
     /**
-     * koþullarda kullanýlan parametreleri ekle
+     * koşullarda kullanılan parametreleri ekle
      */
-    public Olcut ekle(String parametre, Object nesne){
-        this.parametreler.put(parametre,nesne);
+    public Olcut ekle(String parametre, Object nesne) {
+        this.parametreler.put(parametre, nesne);
         return this;
     }
-    
+
     /**
-     * koþullarda kullanýlan parametreleri tümden ekle
+     * koşullarda kullanılan parametreleri tümden ekle
      */
-    public Olcut ekle(Map parametreler){
+    public Olcut ekle(Map parametreler) {
         this.parametreler.putAll(parametreler);
         return this;
     }
-    
-    public String olcutleriAl(){
+
+    public String olcutleriAl() {
         //((1=1) and ((1=1) and (musteri_numuneler_numune_sahibi.rapor_tarihi is null) and (musteri.no = 4)))
         //Musteri.numuneler.deneyler.deneyTip.ad like :p1
         String sonuc = "";
-        metin = metin.replace("(","( ");
-        metin = metin.replace(")"," )");
+        metin = metin.replaceAll("\\(", "\\( ");
+        metin = metin.replaceAll("\\)", " \\)");
         String[] parcalar = metin.split(" ");
         for (int i = 0; i < parcalar.length; i++) {
-            if (!parcalar[i].startsWith(":") && parcalar[i].contains(".")){
-                int sonNokta = parcalar[i].lastIndexOf('.');                
+            if (!parcalar[i].startsWith(":") && parcalar[i].indexOf(".") >= 0) {
+                int sonNokta = parcalar[i].lastIndexOf('.');
                 sonuc += " ";
-                int u = parcalar[i].length();                
-                sonuc +=Cevir.vt(parcalar[i].substring(0,sonNokta).replace('.','_'));
-                sonuc +=Cevir.vt(parcalar[i].substring(sonNokta,u));
-            }else{
-                sonuc += " "+parcalar[i];
+                int u = parcalar[i].length();
+                sonuc += Cevir.vt(parcalar[i].substring(0, sonNokta).replace('.', '_'));
+                sonuc += Cevir.vt(parcalar[i].substring(sonNokta, u));
+            } else {
+                sonuc += " " + parcalar[i];
             }
         }
         return sonuc;
     }
-    
-    public Map parametreler(){
+
+    public Map parametreler() {
         return this.parametreler;
     }
 
     public String toString() {
-        return olcutleriAl()+" "+this.parametreler;
+        return olcutleriAl() + " " + this.parametreler;
     }
-    
 }
Index: /trunk/fmgVen/src/net/fmg/ven/SorguEslestirici.java
===================================================================
--- /trunk/fmgVen/src/net/fmg/ven/SorguEslestirici.java	(revision 20)
+++ /trunk/fmgVen/src/net/fmg/ven/SorguEslestirici.java	(revision 30)
@@ -3,7 +3,7 @@
  *
  * Created on December 18, 2006, 10:40 AM
- * (4.12.06 tarihli SpringDaoDeneme çalýþmasýndan derlenmiþtir)
+ * (4.12.06 tarihli SpringDaoDeneme çalışmasından derlenmiştir)
  *
- * Ven - Ayar Yerine Gelenek veritabaný eriþim nesnesi
+ * Ven - Ayar Yerine Gelenek veritabanı erişim nesnesi
  */
 
@@ -30,5 +30,5 @@
 
 /**
- * 'Ayar yerine gelenek' yaklaþýmýnda üretilmiþ sorgunun sonucunu belirtilen nesneye eþler
+ * 'Ayar yerine gelenek' yaklaşımında üretilmiş sorgunun sonucunu belirtilen nesneye eşler
  * @author Fatih Mehmet Güler
  */
@@ -57,5 +57,5 @@
         long t1 = System.currentTimeMillis();
         final List sonuclar = new LinkedList();
-        final String tabloAdi = Cevir.vt(nesneSinifi.getSimpleName());
+        final String tabloAdi = Cevir.vt(Cevir.isim(nesneSinifi.getName()));
         final Set sutunlar = new HashSet();
         
@@ -67,5 +67,5 @@
         }
         );
-        System.out.println("Listeleme zamaný="+(System.currentTimeMillis()-t1));        
+        System.out.println("Listeleme zamanı="+(System.currentTimeMillis()-t1));        
         return sonuclar;
     }
@@ -73,20 +73,20 @@
     private void esle(ResultSet rs, Set sutunlar, String tabloAdi, Class nesneSinifi, List ustListe){
         try{
-            if (!sutunlar.contains(tabloAdi+"_no")) return; //bu nesne sütunlar arasýnda hiç yok
+            if (!sutunlar.contains(tabloAdi+"_no")) return; //bu nesne sütunlar arasında hiç yok
             Object no = rs.getObject(tabloAdi+"_no");
-            if (no==null) return; //bu nesne sütunlar arasýnda var ama null, muhtemelen left join den dolayý
-            BeanWrapper wr=new BeanWrapperImpl(nesneSinifi); //Zaten class introspectionunu saklýyor (CachedIntrospectionResults.forClass())
+            if (no==null) return; //bu nesne sütunlar arasında var ama null, muhtemelen left join den dolayı
+            BeanWrapper wr=new BeanWrapperImpl(nesneSinifi); //Zaten class introspectionunu saklıyor (CachedIntrospectionResults.forClass())
             wr.setPropertyValue("no",no);
             Object nesne = wr.getWrappedInstance();
             boolean esle = true;
-            for (Iterator it = ustListe.iterator(); it.hasNext();) { //listenin içinde indexOf ve get(i) ile birkaç kez dolaþmak yerinde bir kez dolaþmýþ olalým, onlar da ayný þeyi yapýyor çünkü.
+            for (Iterator it = ustListe.iterator(); it.hasNext();) { //listenin içinde indexOf ve get(i) ile birkaç kez dolaşmak yerinde bir kez dolaşmış olalım, onlar da aynı şeyi yapıyor çünkü.
                 Object listedekiNesne = (Object) it.next();
-                if (nesne.equals(listedekiNesne)){ //NOT: bunu no'larý karþýlaþtýrarak da yapabiliriz
-                    wr.setWrappedInstance(listedekiNesne); //listede zaten var onu kullanmalýyýz
-                    esle = false; // ve tekrar eþleme yapmamalýyýz
+                if (nesne.equals(listedekiNesne)){ //NOT: bunu no'ları karşılaştırarak da yapabiliriz
+                    wr.setWrappedInstance(listedekiNesne); //listede zaten var onu kullanmalıyız
+                    esle = false; // ve tekrar eşleme yapmamalıyız
                     break;
                 }
             }
-            if (esle) ustListe.add(nesne); //bulamadýk, yani listede yok bunu ekliyoruz
+            if (esle) ustListe.add(nesne); //bulamadık, yani listede yok bunu ekliyoruz
             PropertyDescriptor[] pdArr = wr.getPropertyDescriptors();
             for (int i = 0; i < pdArr.length; i++) {
@@ -95,10 +95,10 @@
                 Class alanSinifi = pd.getPropertyType();
                 String sutun = tabloAdi+"_"+alanAdi;
-                if (esle && vtSiniflari.contains(alanSinifi)){ //veritabaný nesneleri
+                if (esle && vtSiniflari.contains(alanSinifi)){ //veritabanı nesneleri
                     if(sutunlar.contains(sutun)){
                         if(hataAyiklama) System.out.println(">>alan bulundu "+sutun);
                         wr.setPropertyValue(pd.getName(),rs.getObject(sutun));
                     }else{
-                        if(hataAyiklama) System.out.println("--alan bulunamadý: "+sutun);
+                        if(hataAyiklama) System.out.println("--alan bulunamadı: "+sutun);
                     }
                 }
@@ -106,9 +106,9 @@
                     if(sutunlar.contains(sutun+"_no")){
                         if(hataAyiklama) System.out.println(">>nesne bulundu "+sutun);
-                        List list = new ArrayList(1); //tek sonuç olacaðýný biliyoruz
+                        List list = new ArrayList(1); //tek sonuç olacağını biliyoruz
                         esle(rs,sutunlar,sutun,alanSinifi,list);
                         if(list.size()>0)wr.setPropertyValue(pd.getName(),list.get(0));
                     }else{
-                        if(hataAyiklama) System.out.println("--nesne bulunamadý: "+sutun);
+                        if(hataAyiklama) System.out.println("--nesne bulunamadı: "+sutun);
                     }
                 }
@@ -119,10 +119,10 @@
                         esle(rs,sutunlar,sutun,bagNesneSinifi,(List)wr.getPropertyValue(pd.getName()));
                     }else{
-                        if(hataAyiklama) System.out.println("--liste bulunamadý: "+sutun);
+                        if(hataAyiklama) System.out.println("--liste bulunamadı: "+sutun);
                     }
                 }
                 
             }
-        } catch(SQLException ex){
+        } catch(Exception ex){
             ex.printStackTrace();
         }
Index: /trunk/fmgVen/src/net/fmg/ven/SorguUretici.java
===================================================================
--- /trunk/fmgVen/src/net/fmg/ven/SorguUretici.java	(revision 20)
+++ /trunk/fmgVen/src/net/fmg/ven/SorguUretici.java	(revision 30)
@@ -3,7 +3,7 @@
  *
  * Created on December 18, 2006, 9:32 AM
- * (4.12.06 tarihli SpringDaoDeneme çalýþmasýndan derlenmiþtir)
+ * (4.12.06 tarihli SpringDaoDeneme çalışmasından derlenmiştir)
  *
- * Ven - Ayar Yerine Gelenek veritabaný eriþim nesnesi
+ * Ven - Ayar Yerine Gelenek veritabanı erişim nesnesi
  */
 
@@ -23,5 +23,5 @@
 
 /**
- * Belirtilen sýnýfýn 'Ayar yerine gelenek' yaklaþýmýnda sorgusunu üretir
+ * Belirtilen sınıfın 'Ayar yerine gelenek' yaklaşımında sorgusunu üretir
  * @author Fatih Mehmet Güler
  */
@@ -50,14 +50,14 @@
         PropertyDescriptor[] pdArr = wr.getPropertyDescriptors();
         for (int i = 0; i < pdArr.length; i++) {
-            Class alanSinifi = pdArr[i].getPropertyType(); //alan sýnýfý
-            String sutunAdi = Cevir.vt(pdArr[i].getName()); //sütun adý
-            String alanAdi = pdArr[i].getName(); //alan adý
-            if (vtSiniflari.contains(alanSinifi)){ //veritabaný direk alan (Integer,String,Date, vs)
+            Class alanSinifi = pdArr[i].getPropertyType(); //alan sınıfı
+            String sutunAdi = Cevir.vt(pdArr[i].getName()); //sütun adı
+            String alanAdi = pdArr[i].getName(); //alan adı
+            if (vtSiniflari.contains(alanSinifi)){ //veritabanı direk alan (Integer,String,Date, vs)
                 selectCumlesi.append(tabloAdi+"."+sutunAdi+" as "+tabloAdi+"_"+sutunAdi); //sütun
                 selectCumlesi.append(", ");
             }
             if (alanSinifi.getPackage()!=null && nesnePaketleri.contains(alanSinifi.getPackage().getName()) && baglarKapsar(baglar,nesneYolu+"."+alanAdi)){ //domain nesnesi 1-1 join
-                String bagTablosuDigerAd = tabloAdi+"_"+sutunAdi; // bað tablosu için diðer ad, çünkü ayný isimde birden fazla bað olabilir, karýþmasýn
-                String bagTablosu = Cevir.vt(alanSinifi.getSimpleName());//gerçek bað tablosu
+                String bagTablosuDigerAd = tabloAdi+"_"+sutunAdi; // bağ tablosu için diğer ad, çünkü aynı isimde birden fazla bağ olabilir, karışmasın
+                String bagTablosu = Cevir.vt(Cevir.isim(alanSinifi.getName()));//gerçek bağ tablosu
                 fromCumlesi.append(" left join "+bagTablosu+" "+bagTablosuDigerAd);
                 fromCumlesi.append(" on "+bagTablosuDigerAd+".no = "+tabloAdi+"."+sutunAdi+"_no");
@@ -66,7 +66,7 @@
             if (wr.getPropertyValue(alanAdi) instanceof SinifBildirenLinkedList && baglarKapsar(baglar,nesneYolu+"."+alanAdi)){
                 Class cokluAlandakiNesneSinifi = (Class)wr.getPropertyValue(alanAdi+".nesneSinifi");
-                String bagTablosuDigerAd = tabloAdi+"_"+sutunAdi; // bað tablosu için diðer ad, çünkü ayný isimde birden fazla bað olabilir, karýþmasýn
-                String bagTablosu = Cevir.vt(cokluAlandakiNesneSinifi.getSimpleName());//gerçek bað tablosu
-                String bagAlani = Cevir.vt((String)wr.getPropertyValue(alanAdi+".bagAlani")); //YAP: bunu vermeden de varsayýlan birþey yapsýn
+                String bagTablosuDigerAd = tabloAdi+"_"+sutunAdi; // bağ tablosu için diğer ad, çünkü aynı isimde birden fazla bağ olabilir, karışmasın
+                String bagTablosu = Cevir.vt(Cevir.isim(cokluAlandakiNesneSinifi.getName()));//gerçek bağ tablosu
+                String bagAlani = Cevir.vt((String)wr.getPropertyValue(alanAdi+".bagAlani")); //YAP: bunu vermeden de varsayılan birşey yapsın
                 fromCumlesi.append(" left join "+bagTablosu+" "+bagTablosuDigerAd);
                 fromCumlesi.append(" on "+bagTablosuDigerAd+"."+bagAlani+"_no = "+tabloAdi+".no");
@@ -93,5 +93,5 @@
     public String secmeSorgusuUret(Set baglar, Class nesneSinifi){
         //long t1 = System.currentTimeMillis();
-        String nesneAdi = nesneSinifi.getSimpleName();
+        String nesneAdi = Cevir.isim(nesneSinifi.getName());
         String tabloAdi = Cevir.vt(nesneAdi);
         StringBuffer selectCumlesi = new StringBuffer("select ");
@@ -99,19 +99,19 @@
         tekrarlayanSorguUret(0,tabloAdi,nesneAdi,nesneSinifi,baglar,selectCumlesi,fromCumlesi);
         selectCumlesi.append(" 1=1");
-        //System.out.println("Sorgu üretme zamaný="+(System.currentTimeMillis()-t1));        
+        //System.out.println("Sorgu üretme zamanı="+(System.currentTimeMillis()-t1));        
         return selectCumlesi.toString()+" \n"+fromCumlesi.toString();
     }
     
     /**
-     * Sql select sorgusu üretir, ancak alanlarý almaz count(distinct tabloadi.no) alýr
+     * Sql select sorgusu üretir, ancak alanları almaz count(distinct tabloadi.no) alır
      */
     public String saymaSorgusuUret(Set baglar, Class nesneSinifi){
         //long t1 = System.currentTimeMillis();
-        String nesneAdi = nesneSinifi.getSimpleName();
+        String nesneAdi = Cevir.isim(nesneSinifi.getName());
         String tabloAdi = Cevir.vt(nesneAdi);
         StringBuffer selectCumlesi = new StringBuffer();
         StringBuffer fromCumlesi = new StringBuffer("from "+tabloAdi);
         tekrarlayanSorguUret(0,tabloAdi,nesneAdi,nesneSinifi,baglar,selectCumlesi,fromCumlesi);
-        //System.out.println("Sorgu üretme zamaný="+(System.currentTimeMillis()-t1));        
+        //System.out.println("Sorgu üretme zamanı="+(System.currentTimeMillis()-t1));        
         return "select count(distinct "+tabloAdi+".no) \n"+fromCumlesi.toString();
     }
@@ -123,5 +123,5 @@
     public String guncellemeSorgusuUret(Object nesne){
         BeanWrapper wr = new BeanWrapperImpl(nesne);
-        String nesneAdi = nesne.getClass().getSimpleName();
+        String nesneAdi = Cevir.isim(nesne.getClass().getName());
         String tabloAdi = Cevir.vt(nesneAdi);
         StringBuffer sorgu;
@@ -133,9 +133,9 @@
             StringBuffer degerler = new StringBuffer(" values(");
             for (int i = 0; i < pdArr.length; i++) {
-                Class alanSinifi = pdArr[i].getPropertyType(); //alan sýnýfý
-                String sutunAdi = Cevir.vt(pdArr[i].getName()); //sütun adý
-                String alanAdi = pdArr[i].getName(); //alan adý
-                if (alanAdi.equals("no")) continue; //YAP: Belki squenci bozar, ama bozmuyosa kaldýr
-                if (vtSiniflari.contains(alanSinifi)){ //veritabaný direk alan (Integer,String,Date, vs)
+                Class alanSinifi = pdArr[i].getPropertyType(); //alan sınıfı
+                String sutunAdi = Cevir.vt(pdArr[i].getName()); //sütun adı
+                String alanAdi = pdArr[i].getName(); //alan adı
+                if (alanAdi.equals("no")) continue; //YAP: Belki squenci bozar, ama bozmuyosa kaldır
+                if (vtSiniflari.contains(alanSinifi)){ //veritabanı direk alan (Integer,String,Date, vs)
                     sorgu.append(sutunAdi);
                     sorgu.append(",");
@@ -159,8 +159,8 @@
             sorgu = new StringBuffer("update "+tabloAdi+" set ");
             for (int i = 0; i < pdArr.length; i++) {
-                Class alanSinifi = pdArr[i].getPropertyType(); //alan sýnýfý
-                String sutunAdi = Cevir.vt(pdArr[i].getName()); //sütun adý
-                String alanAdi = pdArr[i].getName(); //alan adý
-                if (vtSiniflari.contains(alanSinifi)){ //veritabaný direk alan (Integer,String,Date, vs)
+                Class alanSinifi = pdArr[i].getPropertyType(); //alan sınıfı
+                String sutunAdi = Cevir.vt(pdArr[i].getName()); //sütun adı
+                String alanAdi = pdArr[i].getName(); //alan adı
+                if (vtSiniflari.contains(alanSinifi)){ //veritabanı direk alan (Integer,String,Date, vs)
                     sorgu.append(sutunAdi+"=:"+alanAdi);
                     sorgu.append(",");
Index: /trunk/fmgVen/src/net/fmg/ven/Ven.java
===================================================================
--- /trunk/fmgVen/src/net/fmg/ven/Ven.java	(revision 20)
+++ /trunk/fmgVen/src/net/fmg/ven/Ven.java	(revision 30)
@@ -3,7 +3,7 @@
  *
  * Created on December 18, 2006, 5:58 PM
- * (4.12.06 tarihli SpringDaoDeneme çalýþmasýndan derlenmiþtir)
+ * (4.12.06 tarihli SpringDaoDeneme çalışmasından derlenmiştir)
  *
- * Ven - Ayar Yerine Gelenek veritabaný eriþim nesnesi
+ * Ven - Ayar Yerine Gelenek veritabanı erişim nesnesi
  */
 
@@ -24,5 +24,5 @@
 
 /**
- * Veritabaný eriþim nesnesi temel sýnýf
+ * Veritabanı erişim nesnesi temel sınıf
  * @author Fatih Mehmet Güler
  */
@@ -42,11 +42,11 @@
     
     /**
-     * Kullaným No: O kullanýma göre otomatik tespit edeceði baðlarý numaralandýrýr
-     * <p> ÖNEMLÝ: daha bitmedi :)
+     * Kullanım No: O kullanıma göre otomatik tespit edeceği bağları numaralandırır
+     * <p> ÖNEMLİ: daha bitmedi :)
      */
     public List nesneleriAl(Class nesneSinifi, Integer kullanimNo){
         Set baglar = new HashSet();
         kullanimlar.put(kullanimNo,baglar);
-        baglar.add(nesneSinifi.getSimpleName());
+        baglar.add(Cevir.isim(nesneSinifi.getName()));
         
         String sorgu = uretici.secmeSorgusuUret(baglar, nesneSinifi);
@@ -58,5 +58,5 @@
     
     /**
-     * Gönderilen baðlara göre nesneyi iliþkileriyle birlikte veritabanýndan getirir
+     * Gönderilen bağlara göre nesneyi ilişkileriyle birlikte veritabanından getirir
      */
     public List nesneleriAl(Class nesneSinifi, Set baglar){
@@ -69,5 +69,5 @@
     
     /**
-     * Gönderilen baðlara göre nesneyi iliþkileriyle birlikte verilen ölçüte göre veritabanýndan getirir
+     * Gönderilen bağlara göre nesneyi ilişkileriyle birlikte verilen ölçüte göre veritabanından getirir
      * Verilen ölçütlere göre
      */
@@ -83,5 +83,5 @@
     
     /**
-     * Gönderilen baðlara göre nesneyi iliþkileriyle birlikte verilen ölçüte göre veritabanýndan kaç satýr olacaðýný sayar
+     * Gönderilen bağlara göre nesneyi ilişkileriyle birlikte verilen ölçüte göre veritabanından kaç satır olacağını sayar
      * Verilen ölçütlere göre
      */
@@ -94,5 +94,5 @@
     
     /**
-     * Gönderilen baðlara göre nesneyi iliþkileriyle birlikte verilen ölçüte göre veritabanýndan kaç satýr olacaðýný sayar
+     * Gönderilen bağlara göre nesneyi ilişkileriyle birlikte verilen ölçüte göre veritabanından kaç satır olacağını sayar
      * Verilen ölçütlere göre
      */
@@ -106,10 +106,10 @@
     
     /**
-     * Gönderilen baðlara göre nesneyi iliþkileriyle birlikte veritabanýndan getirir
+     * Gönderilen bağlara göre nesneyi ilişkileriyle birlikte veritabanından getirir
      * <p> Sadece Nesne
      */
     public Object nesneAl(Class nesneSinifi, Integer no, Set baglar){
         String sorgu = uretici.secmeSorgusuUret(baglar, nesneSinifi);
-        Olcut olcut = new Olcut().ekle("and "+Cevir.vt(nesneSinifi.getSimpleName())+".no = :___no").ekle("___no",no);
+        Olcut olcut = new Olcut().ekle("and "+Cevir.vt(Cevir.isim(nesneSinifi.getName()))+".no = :___no").ekle("___no",no);
         sorgu += " where 1=1"+olcut.olcutleriAl();
         if(hataAyiklama) System.out.println("SQL: "+sorgu);
@@ -122,10 +122,10 @@
     
     /**
-     * Gönderilen baðlara göre nesneyi iliþkileriyle birlikte verilen ölçüte göre veritabanýndan getirir
+     * Gönderilen bağlara göre nesneyi ilişkileriyle birlikte verilen ölçüte göre veritabanından getirir
      * <p> Sadece Nesne, ölçütlere göre
      */
     public Object nesneAl(Class nesneSinifi, Integer no, Set baglar, Olcut olcut){
         String sorgu = uretici.secmeSorgusuUret(baglar, nesneSinifi);
-        sorgu += " where 1=1 and "+Cevir.vt(nesneSinifi.getSimpleName())+".no = :___no "+olcut.olcutleriAl(); //No diðer ölçütlerden önce gelmeli order-limit için
+        sorgu += " where 1=1 and "+Cevir.vt(Cevir.isim(nesneSinifi.getName()))+".no = :___no "+olcut.olcutleriAl(); //No diğer ölçütlerden önce gelmeli order-limit için
         olcut.ekle("___no",no);
         if(hataAyiklama) System.out.println("SQL: "+sorgu);
@@ -142,13 +142,13 @@
         SqlParameterSource parametreKaynagi = new BeanPropertySqlParameterSource(nesne);
         sablon.update(sorgu,parametreKaynagi);
-        //YAP: yeni eklenenin nosunu almak için daha etkin bir yöntem bulunabilir (üreticinin içinde deki beanwrapper kullanýlabilir vs)
+        //YAP: yeni eklenenin nosunu almak için daha etkin bir yöntem bulunabilir (üreticinin içinde deki beanwrapper kullanılabilir vs)
         BeanWrapper wr = new BeanWrapperImpl(nesne);
         if(wr.getPropertyValue("no")==null){            
-            wr.setPropertyValue("no",new Integer(sablon.queryForInt("select currval('"+Cevir.vt(nesne.getClass().getSimpleName())+"_no')", new HashMap())));
+            wr.setPropertyValue("no",new Integer(sablon.queryForInt("select currval('"+Cevir.vt(Cevir.isim(nesne.getClass().getName()))+"_no')", new HashMap())));
         }
     }
     
     public void nesneSil(Integer no, Class nesneSinifi){
-        String sorgu = "delete from "+Cevir.vt(nesneSinifi.getSimpleName())+" where no = :no ;";
+        String sorgu = "delete from "+Cevir.vt(Cevir.isim(nesneSinifi.getName()))+" where no = :no ;";
         Map parametreler = new HashMap(2);
         parametreler.put("no",no);
@@ -158,5 +158,5 @@
     //SETTERS--------------------------------------------
     public void setDataSource(DataSource dataSource){
-        if (dataSource==null) throw new RuntimeException("DataSource null olamaz!!! Bu koþullar altýnda daha fazla çalýþamam :)");
+        if (dataSource==null) throw new RuntimeException("DataSource null olamaz!!! Bu koşullar altında daha fazla çalışamam :)");
         this.sablon = new NamedParameterJdbcTemplate(dataSource);
         this.eslestirici.setSablon(sablon);
Index: /trunk/fmgVen/src/net/fmg/ven/arac/Cevir.java
===================================================================
--- /trunk/fmgVen/src/net/fmg/ven/arac/Cevir.java	(revision 20)
+++ /trunk/fmgVen/src/net/fmg/ven/arac/Cevir.java	(revision 30)
@@ -3,7 +3,7 @@
  *
  * Created on December 18, 2006, 10:51 AM
- * (4.12.06 tarihli SpringDaoDeneme çalýþmasýndan derlenmiþtir)
+ * (4.12.06 tarihli SpringDaoDeneme çalışmasından derlenmiştir)
  *
- * Ven - Ayar Yerine Gelenek veritabaný eriþim nesnesi
+ * Ven - Ayar Yerine Gelenek veritabanı erişim nesnesi
  */
 
@@ -13,5 +13,5 @@
 
 /**
- * Deve harflerle yazýlmýþ metni veritabaný þekline çevirir
+ * Deve harflerle yazılmış metni veritabanı şekline çevirir
  * @author Fatih Mehmet Güler
  */
@@ -35,4 +35,10 @@
         return sonuc.toString();
     }
+
+    public static String isim(String isim) {
+        int i = isim.lastIndexOf(".");
+        if (i < 0) return isim;
+        return isim.substring(i + 1);
+    }
     
 }
Index: /trunk/fmgVen/src/net/fmg/ven/arac/SinifBildirenLinkedList.java
===================================================================
--- /trunk/fmgVen/src/net/fmg/ven/arac/SinifBildirenLinkedList.java	(revision 20)
+++ /trunk/fmgVen/src/net/fmg/ven/arac/SinifBildirenLinkedList.java	(revision 30)
@@ -12,5 +12,5 @@
 
 /**
- * Ýçinde tuttuðu nesne türünü bildiren linked list
+ * İçinde tuttuğu nesne türünü bildiren linked list
  * @author Fatih
  */
@@ -23,17 +23,17 @@
      */
     public SinifBildirenLinkedList() {                
-        System.out.println("FmgList, normal LinkedList kipinde çalýþýyor...");
+        System.out.println("FmgList, normal LinkedList kipinde çalışıyor...");
     }
     
     /**
-     * içindeki bileþen türü sýnýfý belirt
+     * içindeki bileşen türü sınıfı belirt
      */
     public SinifBildirenLinkedList(Class nesneSinifi) {
         this.nesneSinifi = nesneSinifi;
-        System.out.println("**Uyarý-> bileþen alaný verilmeden çözme henüz yapýlmadý, sorgunuz çalýþmayacak");
+        System.out.println("**Uyarı-> bileşen alanı verilmeden çözme henüz yapılmadı, sorgunuz çalışmayacak");
     }
     
     /**
-     * içindeki bileþen türü sýnýfý ve o sýnýftaki hangi alana birleþtiðini belirt
+     * içindeki bileşen türü sınıfı ve o sınıftaki hangi alana birleştiğini belirt
      */
     public SinifBildirenLinkedList(Class nesneSinifi, String bagAlani) {
@@ -50,7 +50,7 @@
     }
 
-    //zorlamaya gerek yok, sadece türünü belirlemek çabamýz
+    //zorlamaya gerek yok, sadece türünü belirlemek çabamız
     //public boolean add(E o) {
-    //    if (o.getClass()!=nesneSinifi) throw new RuntimeException("Desteklenmeyen bileþen türü!");        
+    //    if (o.getClass()!=nesneSinifi) throw new RuntimeException("Desteklenmeyen bileşen türü!");        
     //    return super.add(o);
     //}
Index: /trunk/fmgVen/test/com/fmguler/ven/LiquibaseUtil.java
===================================================================
--- /trunk/fmgVen/test/com/fmguler/ven/LiquibaseUtil.java	(revision 30)
+++ /trunk/fmgVen/test/com/fmguler/ven/LiquibaseUtil.java	(revision 30)
@@ -0,0 +1,98 @@
+/*
+ *  fmgVen - A Convention over Configuration Java ORM Tool
+ *  Copyright 2011 Fatih Mehmet Güler
+ * 
+ *  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.
+ *  under the License.
+ */
+package com.fmguler.ven;
+
+import java.sql.SQLException;
+import java.util.Locale;
+import javax.sql.DataSource;
+import liquibase.FileSystemFileOpener;
+import liquibase.Liquibase;
+import liquibase.database.Database;
+import liquibase.database.DatabaseFactory;
+import liquibase.exception.JDBCException;
+import liquibase.exception.LiquibaseException;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+
+/**
+ * Database utilities for testing
+ * 
+ * @author Fatih Mehmet Güler
+ */
+public class LiquibaseUtil {
+    /**
+     * @return DataSource for the test database
+     */
+    public static DataSource getDataSource() {
+        DriverManagerDataSource ds = new DriverManagerDataSource();
+        ds.setDriverClassName("org.postgresql.Driver");
+        ds.setUsername("postgres");
+        ds.setPassword("qwerty");
+        ds.setUrl("jdbc:postgresql://127.0.0.1:5432/ven-test");
+        return ds;
+    }
+
+    /**
+     * Build the test database
+     */
+    public static void buildDatabase() {
+        try {
+            Locale currLocale = Locale.getDefault();
+            Locale.setDefault(Locale.ENGLISH);
+            Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(getDataSource().getConnection());
+            Liquibase liquibase = new Liquibase("etc/test-db/test-db-changelog.xml", new FileSystemFileOpener(), database);
+            liquibase.update("");
+            Locale.setDefault(currLocale);
+        } catch (SQLException ex) {
+            ex.printStackTrace();
+        } catch (JDBCException ex) {
+            ex.printStackTrace();
+        } catch (LiquibaseException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    /**
+     * Undo all changes in the test database
+     */
+    public static void rollbackDatabase(String tag) {
+        try {
+            Locale currLocale = Locale.getDefault();
+            Locale.setDefault(Locale.ENGLISH);
+            Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(getDataSource().getConnection());
+            Liquibase liquibase = new Liquibase("etc/test-db/test-db-changelog.xml", new FileSystemFileOpener(), database);
+            liquibase.rollback(tag, "");
+            Locale.setDefault(currLocale);
+        } catch (SQLException ex) {
+            ex.printStackTrace();
+        } catch (JDBCException ex) {
+            ex.printStackTrace();
+        } catch (LiquibaseException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    /**
+     * Quick test
+     */
+    public static void main(String[] args) {
+        //buildDatabase();
+        //rollbackDatabase("tag-no-data");
+        rollbackDatabase("tag-init");
+
+    }
+}
Index: /trunk/fmgVen/test/com/fmguler/ven/sample/Sample.java
===================================================================
--- /trunk/fmgVen/test/com/fmguler/ven/sample/Sample.java	(revision 30)
+++ /trunk/fmgVen/test/com/fmguler/ven/sample/Sample.java	(revision 30)
@@ -0,0 +1,190 @@
+/*
+ *  fmgVen - A Convention over Configuration Java ORM Tool
+ *  Copyright 2010 Fatih Mehmet Güler
+ * 
+ *  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.
+ *  under the License.
+ */
+package com.fmguler.ven.sample;
+
+import com.fmguler.ven.Criteria;
+import com.fmguler.ven.LiquibaseUtil;
+import com.fmguler.ven.Ven;
+import com.fmguler.ven.sample.domain.AnotherDomainObject;
+import com.fmguler.ven.sample.domain.SomeDomainObject;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Demonstrates sample usage of fmgVen.
+ * @author Fatih Mehmet Güler
+ */
+public class Sample {
+    public static void main(String[] args) {
+        //build the sample database
+        LiquibaseUtil.buildDatabase();
+
+        //save an object
+        testSave();
+        //get an object
+        testGet();
+        //list the objects
+        testList();
+        //list the objects by some criteria string
+        testListByCriteriaString();
+        //list the objects by some typed criteria
+        testListByCriteriaObject();
+        //delete an object
+        testDelete();
+
+        //rollback the sample database to original state
+        LiquibaseUtil.rollbackDatabase("tag-init");
+    }
+
+    /**
+     * Test save an object
+     */
+    public static void testSave() {
+        System.out.println("******SAVE******");
+        Ven ven = getVen();
+
+        //insert
+        SomeDomainObject obj = new SomeDomainObject();
+        obj.setName("name");
+        obj.setDescription("desc");
+        obj.setDate(new Date());
+        ven.save(obj);
+        System.out.println(obj);
+
+        //update
+        obj.setName("name update");
+        ven.save(obj);
+        System.out.println(obj);
+    }
+
+    /**
+     * Test delete an object
+     */
+    public static void testDelete() {
+        System.out.println("******DELETE******");
+        Ven ven = getVen();
+        ven.delete(2, SomeDomainObject.class);
+    }
+
+    /**
+     * Test get an object by primary key
+     */
+    public static void testGet() {
+        System.out.println("******GET******");
+        Ven ven = getVen();
+
+        //get with includes
+        Set joins = new HashSet();
+        joins.add("SomeDomainObject.anotherDomainObjects");
+        joins.add("SomeDomainObject.anotherDomainObject");
+        SomeDomainObject obj = (SomeDomainObject)ven.get(1, SomeDomainObject.class, joins);
+        System.out.println(obj);
+
+        Set joins2 = new HashSet();
+        joins2.add("AnotherDomainObject.someDomainObject");
+        AnotherDomainObject obj2 = (AnotherDomainObject)ven.get(1, AnotherDomainObject.class, joins2);
+        System.out.println(obj2);
+    }
+
+    /**
+     * Test list the collection of objects
+     */
+    public static void testList() {
+        System.out.println("******LIST******");
+        Ven ven = getVen();
+
+        //list with includes
+        Set joins = new HashSet();
+        joins.add("SomeDomainObject.anotherDomainObjects");
+        joins.add("SomeDomainObject.anotherDomainObject");
+        List objList = ven.list(SomeDomainObject.class, joins);
+
+        Iterator it = objList.iterator();
+        while (it.hasNext()) {
+            SomeDomainObject someDomainObject = (SomeDomainObject)it.next();
+            System.out.println(someDomainObject);
+        }
+    }
+
+    /**
+     * Test list the collection of objects by some criteria (string)
+     */
+    public static void testListByCriteriaString() {
+        Ven ven = getVen();
+
+        //these objects will be included
+        Set joins = new HashSet();
+        joins.add("SomeDomainObject.anotherDomainObjects");
+        joins.add("SomeDomainObject.anotherDomainObject");
+
+        //the results will be filtered according to this criteria
+        Criteria criteria = new Criteria() //criteria object
+                //.param("and SomeDomainObject.name like :p1").param("p1", "s%")
+                .add("and SomeDomainObject.anotherDomainObjects.name like :p2").param("p2", "a%");
+
+
+        //list with includes and criteria
+        List objList = ven.list(SomeDomainObject.class, joins, criteria);
+
+        //print the results
+        Iterator it = objList.iterator();
+        while (it.hasNext()) {
+            SomeDomainObject someDomainObject = (SomeDomainObject)it.next();
+            System.out.println(someDomainObject);
+        }
+    }
+
+    /**
+     * Test list the collection of objects by some criteria (object)
+     */
+    public static void testListByCriteriaObject() {
+        Ven ven = getVen();
+
+        //these objects will be included
+        Set joins = new HashSet();
+        joins.add("SomeDomainObject.anotherDomainObjects");
+        joins.add("SomeDomainObject.anotherDomainObject");
+
+        //the results will be filtered according to this criteria
+        Criteria criteria = new Criteria() //criteria object
+                .like("SomeDomainObject.anotherDomainObjects.name", "a%") //attribute like value
+                .eq("SomeDomainObject.name", "sdo1") //attribute equals value
+                .and(); //connects previous criteria with and
+
+        //list with includes and criteria
+        List objList = ven.list(SomeDomainObject.class, joins, criteria);
+
+        //print the results
+        Iterator it = objList.iterator();
+        while (it.hasNext()) {
+            SomeDomainObject someDomainObject = (SomeDomainObject)it.next();
+            System.out.println(someDomainObject);
+        }
+    }
+
+    //---------------------------------------------------------
+    private static Ven getVen() {
+        Ven ven = new Ven();
+        ven.setDataSource(LiquibaseUtil.getDataSource());
+        ven.addDomainPackage("com.fmguler.ven.sample.domain").addDomainPackage("another.package");
+        return ven;
+    }
+}
Index: /trunk/fmgVen/test/com/fmguler/ven/sample/domain/AnotherDomainObject.java
===================================================================
--- /trunk/fmgVen/test/com/fmguler/ven/sample/domain/AnotherDomainObject.java	(revision 30)
+++ /trunk/fmgVen/test/com/fmguler/ven/sample/domain/AnotherDomainObject.java	(revision 30)
@@ -0,0 +1,106 @@
+/*
+ *  fmgVen - A Convention over Configuration Java ORM Tool
+ *  Copyright 2011 Fatih Mehmet Güler
+ * 
+ *  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.
+ *  under the License.
+ */
+package com.fmguler.ven.sample.domain;
+
+import java.util.Date;
+
+/**
+ *
+ * @author Fatih Mehmet Güler
+ */
+public class AnotherDomainObject {
+    private Integer id;
+    private String name;
+    private String description;
+    private Date date;
+    private SomeDomainObject someDomainObject;
+
+    /**
+     * @return the id
+     */
+    public Integer getId() {
+        return id;
+    }
+
+    /**
+     * @param id the id to set
+     */
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @param name the name to set
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @return the description
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * @param description the description to set
+     */
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    /**
+     * @return the date
+     */
+    public Date getDate() {
+        return date;
+    }
+
+    /**
+     * @param date the date to set
+     */
+    public void setDate(Date date) {
+        this.date = date;
+    }
+
+    /**
+     * @return the someDomainObject
+     */
+    public SomeDomainObject getSomeDomainObject() {
+        return someDomainObject;
+    }
+
+    /**
+     * @param someDomainObject the someDomainObject to set
+     */
+    public void setSomeDomainObject(SomeDomainObject someDomainObject) {
+        this.someDomainObject = someDomainObject;
+    }
+
+    public String toString() {
+        return "{" + id + ", " + name + ", " + description + ", some domain object: " + someDomainObject + "}";
+    }
+}
Index: /trunk/fmgVen/test/com/fmguler/ven/sample/domain/SomeDomainObject.java
===================================================================
--- /trunk/fmgVen/test/com/fmguler/ven/sample/domain/SomeDomainObject.java	(revision 30)
+++ /trunk/fmgVen/test/com/fmguler/ven/sample/domain/SomeDomainObject.java	(revision 30)
@@ -0,0 +1,116 @@
+/*
+ *  fmgVen - A Convention over Configuration Java ORM Tool
+ *  Copyright 2010 Fatih Mehmet Güler
+ * 
+ *  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.
+ *  under the License.
+ */
+package com.fmguler.ven.sample.domain;
+
+import com.fmguler.ven.util.VenList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ *
+ * @author Fatih Mehmet Güler
+ */
+public class SomeDomainObject {
+    private Integer id;
+    private String name;
+    private String description;
+    private Date date;
+    private List anotherDomainObjects = new VenList(AnotherDomainObject.class, "someDomainObject");
+    private AnotherDomainObject anotherDomainObject = new AnotherDomainObject();
+
+    /**
+     * @return the id
+     */
+    public Integer getId() {
+        return id;
+    }
+
+    /**
+     * @param id the id to set
+     */
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @param name the name to set
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @return the description
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * @param description the description to set
+     */
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    /**
+     * @return the date
+     */
+    public Date getDate() {
+        return date;
+    }
+
+    /**
+     * @param date the date to set
+     */
+    public void setDate(Date date) {
+        this.date = date;
+    }
+
+    /**
+     * @return the list of AnotherDomainObject
+     */
+    public List getAnotherDomainObjects() {
+        return anotherDomainObjects;
+    }
+
+    /**
+     * @return the anotherDomainObject
+     */
+    public AnotherDomainObject getAnotherDomainObject() {
+        return anotherDomainObject;
+    }
+
+    /**
+     * @param anotherDomainObject the anotherDomainObject to set
+     */
+    public void setAnotherDomainObject(AnotherDomainObject anotherDomainObject) {
+        this.anotherDomainObject = anotherDomainObject;
+    }
+
+    public String toString() {
+        return "{" + id + ", " + name + ", " + description + ", another domain object: " + anotherDomainObject + ", another domain objects: " + anotherDomainObjects + "} ";
+    }
+}
