Index: trunk/fmgVen/src/com/fmguler/ven/QueryGenerator.java
===================================================================
--- trunk/fmgVen/src/com/fmguler/ven/QueryGenerator.java	(revision 25)
+++ trunk/fmgVen/src/com/fmguler/ven/QueryGenerator.java	(revision 26)
@@ -18,6 +18,11 @@
 package com.fmguler.ven;
 
+import com.fmguler.ven.util.Convert;
+import java.beans.PropertyDescriptor;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.Set;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
 
 /**
@@ -27,7 +32,15 @@
 public class QueryGenerator {
     private Set domainPackages;
+    private Set dbClasses;
 
     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);
     }
 
@@ -40,9 +53,77 @@
     }
 
-    public String generateUpdateQuery() {
-        return null;
+    public String generateInsertQuery(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();
+
+        //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();
     }
 
-    //SETTERS-------------------------------------------------------------------
+    /**
+     * Generates insert/update query
+     * @return the insert 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 ;"); //TODO: remove the last comma
+        return query.toString();
+    }
+
+    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');";
+    }
+
+    //--------------------------------------------------------------------------
+    //SETTERS
     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 25)
+++ trunk/fmgVen/src/com/fmguler/ven/Ven.java	(revision 26)
@@ -18,7 +18,12 @@
 package com.fmguler.ven;
 
+import java.util.HashMap;
 import java.util.List;
 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;
 
 /**
@@ -44,15 +49,56 @@
     }
 
-    public Object get(int no, Class objectClass) {
+    public Object get(int id, Class objectClass) {
         return null;
     }
 
+    /**
+     * Save the object. If it has a "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);
     }
 
-    public void delete(int no, Class objectClass) {
+    public void delete(int id, Class objectClass) {
     }
 
-    //SETTERS-------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    //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
     public void setDataSource(DataSource dataSource) {
         if (dataSource == null) throw new RuntimeException("fmgVen - DataSource cannot be null");
Index: trunk/fmgVen/src/com/fmguler/ven/VenException.java
===================================================================
--- trunk/fmgVen/src/com/fmguler/ven/VenException.java	(revision 26)
+++ trunk/fmgVen/src/com/fmguler/ven/VenException.java	(revision 26)
@@ -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 26)
+++ trunk/fmgVen/src/com/fmguler/ven/util/Convert.java	(revision 26)
@@ -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/net/fmg/ven/Olcut.java
===================================================================
--- trunk/fmgVen/src/net/fmg/ven/Olcut.java	(revision 25)
+++ trunk/fmgVen/src/net/fmg/ven/Olcut.java	(revision 26)
@@ -7,5 +7,4 @@
  * Ven - Ayar Yerine Gelenek veritabanı erişim nesnesi
  */
-
 package net.fmg.ven;
 
@@ -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
      */
-    public Olcut ekle(String kosul){
-        this.metin +=" "+kosul;
+    public Olcut ekle(String kosul) {
+        this.metin += " " + kosul;
         return this;
     }
-    
+
     /**
      * 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
      */
-    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 25)
+++ trunk/fmgVen/src/net/fmg/ven/SorguEslestirici.java	(revision 26)
@@ -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();
         
Index: trunk/fmgVen/src/net/fmg/ven/SorguUretici.java
===================================================================
--- trunk/fmgVen/src/net/fmg/ven/SorguUretici.java	(revision 25)
+++ trunk/fmgVen/src/net/fmg/ven/SorguUretici.java	(revision 26)
@@ -59,5 +59,5 @@
             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 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");
@@ -67,5 +67,5 @@
                 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 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);
@@ -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 ");
@@ -108,5 +108,5 @@
     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();
@@ -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;
Index: trunk/fmgVen/src/net/fmg/ven/Ven.java
===================================================================
--- trunk/fmgVen/src/net/fmg/ven/Ven.java	(revision 25)
+++ trunk/fmgVen/src/net/fmg/ven/Ven.java	(revision 26)
@@ -48,5 +48,5 @@
         Set baglar = new HashSet();
         kullanimlar.put(kullanimNo,baglar);
-        baglar.add(nesneSinifi.getSimpleName());
+        baglar.add(Cevir.isim(nesneSinifi.getName()));
         
         String sorgu = uretici.secmeSorgusuUret(baglar, nesneSinifi);
@@ -111,5 +111,5 @@
     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);
@@ -127,5 +127,5 @@
     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);
@@ -145,10 +145,10 @@
         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);
Index: trunk/fmgVen/src/net/fmg/ven/arac/Cevir.java
===================================================================
--- trunk/fmgVen/src/net/fmg/ven/arac/Cevir.java	(revision 25)
+++ trunk/fmgVen/src/net/fmg/ven/arac/Cevir.java	(revision 26)
@@ -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);
+    }
     
 }
