private String getTableDefinitions(List<Function> atoms,
									   AliasIndex index,
									   String JOIN_KEYWORD,
									   boolean parenthesis,
									   String indent) {

		List<String> tables = getTableDefs(atoms, index, INDENT + indent);
		switch (tables.size()) {
			case 0:
				throw new RuntimeException("Cannot generate definition for empty data");

			case 1:
				return tables.get(0);

			default:
				String JOIN = "%s\n" + indent + JOIN_KEYWORD + "\n" + INDENT + indent + "%s";
				/*
		 		 * Now we generate the table definition: Join/LeftJoin
				 * (possibly nested if there are more than 2 table definitions in the
				 * current list) in case this method was called recursively.
				 *
				 * To form the JOIN we will cycle through each data definition,
				 * nesting the JOINs as we go. The conditions in the ON clause will
				 * go on the TOP level only.
				 */
				int size = tables.size();
				String currentJoin = tables.get(size - 1);

				currentJoin = String.format(JOIN, tables.get(size - 2),
						parenthesis ? inBrackets(currentJoin) : currentJoin);

				for (int i = size - 3; i >= 0; i--) {
					currentJoin = String.format(JOIN, tables.get(i), inBrackets(currentJoin));
				}

				Set<String> on = getConditionsSet(atoms, index, true);

				if (on.isEmpty())
					return currentJoin;

				StringBuilder sb = new StringBuilder();
				sb.append(currentJoin).append("\n").append(indent).append("ON ");
				Joiner.on(" AND\n" + indent).appendTo(sb, on);
				return sb.toString();
		}
	}
private String getTableDefinitions ( List < Function > atoms , AliasIndex index , String JOIN_KEYWORD , boolean parenthesis , String indent ) { List < String > tables = getTableDefs ( atoms , index , INDENT + indent ) ; switch ( tables . size ( ) ) { case 0 : throw new RuntimeException ( "Cannot generate definition for empty data" ) ; case 1 : return tables . get ( 0 ) ; default : String JOIN = "%s\n" + indent + JOIN_KEYWORD + "\n" + INDENT + indent + "%s" ; int size = tables . size ( ) ; String currentJoin = tables . get ( size - 1 ) ; currentJoin = String . format ( JOIN , tables . get ( size - 2 ) , parenthesis ? inBrackets ( currentJoin ) : currentJoin ) ; for ( int i = size - 3 ; i >= 0 ; i -- ) { currentJoin = String . format ( JOIN , tables . get ( i ) , inBrackets ( currentJoin ) ) ; } Set < String > on = getConditionsSet ( atoms , index , true ) ; if ( on . isEmpty ( ) ) return currentJoin ; StringBuilder sb = new StringBuilder ( ) ; sb . append ( currentJoin ) . append ( "\n" ) . append ( indent ) . append ( "ON " ) ; Joiner . on ( " AND\n" + indent ) . appendTo ( sb , on ) ; return sb . toString ( ) ; } }
Returns the table definition for these atoms. By default, a list of atoms
represents JOIN or LEFT JOIN of all the atoms, left to right. All boolean
atoms in the list are considered conditions in the ON clause of the JOIN.

<p>
If the list is a LeftJoin, then it can only have 2 data atoms, and it HAS
to have 2 data atoms.

<p>
If process boolean operators is enabled, all boolean conditions will be
added to the ON clause of the first JOIN.

@param atoms
@param index
@param JOIN_KEYWORD
@param parenthesis
@param indent

@return