}
    public String assembleJoinClause(String leftName,                                     String rightName,                                     int semantic) {        if (disableOuterJoins == true) {            return super.assembleJoinClause(leftName, rightName, semantic);        }                StringBuffer sb = new StringBuffer();        String leftAlias = leftName.substring(0, leftName.indexOf("."));        String rightAlias = rightName.substring(0, rightName.indexOf("."));                String leftCol = leftName.substring(leftName.indexOf(".") + 1);        String rightCol = rightName.substring(rightName.indexOf(".") + 1);                NSArray k;        EOEntity rightEntity;        EOEntity leftEntity;        String relationshipKey = null;        EORelationship r;                        if (leftAlias.equals("t0")) {            leftEntity = entity();        } else {            k = aliasesByRelationshipPath().allKeysForObject(leftAlias);            relationshipKey = k.count()>0? (String)k.lastObject() : "";            leftEntity = entityForKeyPath(relationshipKey);        }                if (rightAlias.equals("t0")) {            rightEntity = entity();        } else {            k = aliasesByRelationshipPath().allKeysForObject(rightAlias);            relationshipKey = k.count()>0? (String)k.lastObject() : "";            rightEntity = entityForKeyPath(relationshipKey);        }        int dotIndex = relationshipKey.indexOf( "." );        relationshipKey = dotIndex == -1            ? relationshipKey            : relationshipKey.substring( relationshipKey.lastIndexOf( "." ) + 1 );        r = rightEntity.anyRelationshipNamed( relationshipKey );        if( r == null )             r = leftEntity.anyRelationshipNamed( relationshipKey );        String rightTable = rightEntity.externalName();        String leftTable = leftEntity.externalName();                JoinClause jc = new JoinClause();                jc.table1 = leftTable + " " + leftAlias;                switch (semantic) {            case EORelationship.LeftOuterJoin:                jc.op = " LEFT OUTER JOIN ";                break;            case EORelationship.RightOuterJoin:                jc.op = " RIGHT OUTER JOIN ";                break;            case EORelationship.FullOuterJoin:                jc.op = " FULL OUTER JOIN ";                break;            case EORelationship.InnerJoin:                jc.op = " INNER JOIN ";                break;        }                jc.table2 = rightTable + " " + rightAlias;        NSArray destCols = (NSArray) r.destinationAttributes().valueForKey( "columnName" );        NSArray sourceCols = (NSArray) r.sourceAttributes().valueForKey( "columnName" );        NSArray joins = r.joins();        int joinsCount = joins.count();        NSMutableArray joinStrings = new NSMutableArray( joinsCount );        for( int i = 0; i < joinsCount; i++ ) {            EOJoin currentJoin = (EOJoin)joins.objectAtIndex(i);            joinStrings.addObject                ( leftAlias +"."+ currentJoin.sourceAttribute().columnName() + " = " +                   rightAlias +"."+ currentJoin.destinationAttribute().columnName() );        }        jc.joinCondition = " ON " + joinStrings.componentsJoinedByString( " AND " );        if( !_alreadyJoined.containsObject( jc ) ) {            _alreadyJoined.insertObjectAtIndex(jc, 0);            return jc.toString();        }        return null;    }