EMPIREDB-402
Added on() functions on DBRowset in order to create join expressions
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBCommand.java b/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
index f2ba88c..9d4aa9c 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
@@ -673,9 +673,9 @@
      */
     public DBCommand join(DBJoinExpr join)
     {
-        // check tables
+        // Rowsets must be different
         if (join.getLeftTable().equals(join.getRightTable()))
-            throw new InvalidArgumentException("left|right", join.getLeftTable());
+            throw new ObjectNotValidException(join, "The rowsets of a join expression must not be the same!");     
         // create list
         if (joins == null)
             joins = new ArrayList<DBJoinExpr>();
@@ -696,18 +696,6 @@
     }
 
     /**
-     * Adds an inner join based on two columns to the list of join expressions.
-     * 
-     * @param left the left join value
-     * @param right the right join
-     * @return itself (this) 
-     */
-    public final DBCommand join(DBColumnExpr left, DBColumn right, DBCompareExpr... addlConstraints)
-    {
-        return join(left, right, DBJoinType.INNER, addlConstraints);
-    }
-
-    /**
      * Adds a left join to the list of join expressions.
      * @return itself (this) 
      */
@@ -718,20 +706,6 @@
     }
 
     /**
-     * Adds a left join based on two columns to the list of join expressions.
-     * Added for convenience
-     * Same as join(left, right, DBJoinType.LEFT);
-     * 
-     * @param left the left join value
-     * @param right the right join
-     * @return itself (this) 
-     */
-    public final DBCommand joinLeft(DBColumnExpr left, DBColumn right, DBCompareExpr... addlConstraints)
-    {
-        return join(left, right, DBJoinType.LEFT, addlConstraints);
-    }
-
-    /**
      * Adds a left join to the list of join expressions.
      * @return itself (this) 
      */
@@ -742,9 +716,37 @@
     }
 
     /**
+     * Adds an inner join based on two columns to the list of join expressions.
+     * 
+     * New in release 3.1: Use join(left.on(right).and(addlConstraint)) instead
+     * 
+     * @param left the left join value
+     * @param right the right join
+     * @return itself (this) 
+     */
+    public final DBCommand join(DBColumnExpr left, DBColumn right, DBCompareExpr... addlConstraints)
+    {
+        return join(left, right, DBJoinType.INNER, addlConstraints);
+    }
+
+    /**
+     * Adds a left join based on two columns to the list of join expressions.
+     * 
+     * New in release 3.1: Use joinLeft(left.on(right).and(addlConstraint)) instead
+     * 
+     * @param left the left join value
+     * @param right the right join
+     * @return itself (this) 
+     */
+    public final DBCommand joinLeft(DBColumnExpr left, DBColumn right, DBCompareExpr... addlConstraints)
+    {
+        return join(left, right, DBJoinType.LEFT, addlConstraints);
+    }
+
+    /**
      * Adds a right join based on two columns to the list of join expressions.
-     * Added for convenience
-     * Same as join(left, right, DBJoinType.RIGHT);
+     * 
+     * New in release 3.1: Use joinRight(left.on(right).and(addlConstraint)) instead
      * 
      * @param left the left join value
      * @param right the right join
@@ -831,6 +833,9 @@
     
     /**
      * Adds a cross join for two tables or views 
+     * 
+     * New in release 3.1: Use left.on(right)) instead
+     * 
      * @param left the left RowSet
      * @param right the right RowSet
      * @return itself (this) 
@@ -846,6 +851,8 @@
     /**
      * Adds a join based on a compare expression to the command.
      * 
+     * New in release 3.1: Use joinLeft(rowset.on(cmp)) instead
+     * 
      * @param rowset table or view to join
      * @param cmp the compare expression with which to join the table
      * @param joinType type of join ({@link DBJoinType#INNER}, {@link DBJoinType#LEFT}, {@link DBJoinType#RIGHT})
@@ -861,6 +868,8 @@
     /**
      * Adds an inner join based on a compare expression to the command.
      * 
+     * New in release 3.1: Use rowset.on(cmp) instead
+     * 
      * @param rowset table of view which to join
      * @param cmp the compare expression with wich to join the table
      * @return itself (this) 
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
index 76d06bc..66cf239 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
@@ -49,6 +49,8 @@
 import org.apache.empire.db.expr.column.DBCountExpr;
 import org.apache.empire.db.expr.compare.DBCompareColExpr;
 import org.apache.empire.db.expr.compare.DBCompareExpr;
+import org.apache.empire.db.expr.join.DBCompareJoinExpr;
+import org.apache.empire.db.expr.join.DBCrossJoinExpr;
 import org.apache.empire.db.list.DBBeanFactoryCache;
 import org.apache.empire.db.list.DBBeanListFactory;
 import org.apache.empire.db.list.DBBeanListFactoryImpl;
@@ -603,6 +605,24 @@
     {
         return columns.get(index);
     }
+    
+    /**
+     * Creates a join expression based on a compare expression
+     */
+    public DBCompareJoinExpr on(DBCompareExpr cmp)
+    {
+        DBCompareJoinExpr join = new DBCompareJoinExpr(this, cmp, DBJoinType.INNER); 
+        return join;
+    }
+    
+    /**
+     * Creates a cross join expression
+     */
+    public DBCrossJoinExpr on(DBRowSet right)
+    {
+        DBCrossJoinExpr join = new DBCrossJoinExpr(this, right);
+        return join;
+    }
 
     /**
      * Initializes a DBRecord for this RowSet and sets primary key values.
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/join/DBCrossJoinExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/join/DBCrossJoinExpr.java
index 25c3f4c..3f48d63 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/join/DBCrossJoinExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/join/DBCrossJoinExpr.java
@@ -27,6 +27,7 @@
 import org.apache.empire.db.DBJoinType;
 import org.apache.empire.db.DBRowSet;
 import org.apache.empire.db.DBSQLBuilder;
+import org.apache.empire.exceptions.NotSupportedException;
 
 /**
  * This class is used for building a join expression of an SQL statement.
@@ -121,6 +122,15 @@
     {
         return null; // no outer table!
     }
+    
+    /**
+     * alters the join type for this join
+     */
+    @Override
+    public void setType(DBJoinType type)
+    {
+        throw new NotSupportedException(this, "joinType:"+type.name());
+    }
 
     /**
      * This function swaps the left and the right statements of the join expression.
diff --git a/empire-db/src/main/java/org/apache/empire/exceptions/ObjectNotValidException.java b/empire-db/src/main/java/org/apache/empire/exceptions/ObjectNotValidException.java
index 2f503e9..7ff3e5e 100644
--- a/empire-db/src/main/java/org/apache/empire/exceptions/ObjectNotValidException.java
+++ b/empire-db/src/main/java/org/apache/empire/exceptions/ObjectNotValidException.java
@@ -24,16 +24,21 @@
 {

     private static final long serialVersionUID = 1L;

     

-    public static final ErrorType errorType = new ErrorType("error.objectNotValid", "The object of type {0} has not been initialized.");

+    public static final ErrorType errorType = new ErrorType("error.objectNotValid", "The object {0} is invalid: {1}");

 

-    public ObjectNotValidException(Class<?> clazz)

+    public ObjectNotValidException(Class<?> clazz, String message)

     {

-        super(errorType, new String[] { (clazz!=null) ? clazz.getName() : "{unknown}" } );

+        super(errorType, new String[] { (clazz!=null) ? clazz.getName() : "{unknown}", message } );

+    }

+    

+    public ObjectNotValidException(Object obj, String message)

+    {

+        this((obj!=null) ? obj.getClass() : null, message);

     }

     

     public ObjectNotValidException(Object obj)

     {

-        this((obj!=null) ? obj.getClass() : null);

+        this((obj!=null) ? obj.getClass() : null, "Not initialized");

     }

 

 }