Source:
<code><START> private FromItem parseJoinItem(final FromItem leftFromItem,final String itemToken,Set<FromItem> fromItems) { <END> final int indexOfJoin = itemToken.toUpperCase().indexOf(" JOIN "); final String firstPart = itemToken.substring(0, indexOfJoin).trim(); final String secondPart = itemToken.substring(indexOfJoin + " JOIN ".length()).trim(); final int indexOfJoinType = firstPart.lastIndexOf(" "); final String joinTypeString = firstPart.substring(indexOfJoinType).trim().toUpperCase(); final JoinType joinType = JoinType.valueOf(joinTypeString); final String firstTableToken = firstPart.substring(0, indexOfJoinType).trim(); final int indexOfOn = secondPart.toUpperCase().indexOf(" ON "); final String secondTableToken = secondPart.substring(0, indexOfOn).trim(); final FromItem leftSide = parseTableItem(firstTableToken); final FromItem rightSide = parseTableItem(secondTableToken); fromItems.add(leftSide); final String[] onClauses = secondPart.substring(indexOfOn + " ON ".length()).split(" AND "); final SelectItem[] leftOn = new SelectItem[onClauses.length]; final SelectItem[] rightOn = new SelectItem[onClauses.length]; for (int i = 0; i < onClauses.length; i++) { final String onClause = onClauses[i]; final int indexOfEquals = onClause.indexOf("="); final String leftPart = onClause.substring(0, indexOfEquals).trim(); final String rightPart = onClause.substring(indexOfEquals + 1).trim(); leftOn[i] = findSelectItem(leftPart, fromItems.toArray(new FromItem[fromItems.size()]), rightSide); rightOn[i] = findSelectItem(rightPart, fromItems.toArray(new FromItem[fromItems.size()]), rightSide); } final FromItem leftItem = (leftFromItem != null) ? leftFromItem : leftSide; final FromItem result = new FromItem(joinType, leftItem, rightSide, leftOn, rightOn); result.setQuery(_query); return result; }</code><technical_language>minor, I missing some spaces commas :-)</technical_language>

Target:
private FromItem parseJoinItem(final FromItem leftFromItem, final String itemToken, Set<FromItem> fromItems) { final int indexOfJoin = itemToken.toUpperCase().indexOf(" JOIN "); final String firstPart = itemToken.substring(0, indexOfJoin).trim(); final String secondPart = itemToken.substring(indexOfJoin + " JOIN ".length()).trim(); final int indexOfJoinType = firstPart.lastIndexOf(" "); final String joinTypeString = firstPart.substring(indexOfJoinType).trim().toUpperCase(); final JoinType joinType = JoinType.valueOf(joinTypeString); final String firstTableToken = firstPart.substring(0, indexOfJoinType).trim(); final int indexOfOn = secondPart.toUpperCase().indexOf(" ON "); final String secondTableToken = secondPart.substring(0, indexOfOn).trim(); final FromItem leftSide = parseTableItem(firstTableToken); final FromItem rightSide = parseTableItem(secondTableToken); fromItems.add(leftSide); fromItems.add(rightSide); final String[] onClauses = secondPart.substring(indexOfOn + " ON ".length()).split(" AND "); final SelectItem[] leftOn = new SelectItem[onClauses.length]; final SelectItem[] rightOn = new SelectItem[onClauses.length]; for (int i = 0; i < onClauses.length; i++) { final String onClause = onClauses[i]; final int indexOfEquals = onClause.indexOf("="); final String leftPart = onClause.substring(0, indexOfEquals).trim(); final String rightPart = onClause.substring(indexOfEquals + 1).trim(); leftOn[i] = findSelectItem(leftPart, fromItems.toArray(new FromItem[fromItems.size()])); rightOn[i] = findSelectItem(rightPart, fromItems.toArray(new FromItem[fromItems.size()])); } final FromItem leftItem = (leftFromItem != null) ? leftFromItem : leftSide; final FromItem result = new FromItem(joinType, leftItem, rightSide, leftOn, rightOn); result.setQuery(_query); return result; }