private void doPathExpression(String token, QueryTranslatorImpl q) throws QueryException { preprocess(token, q); StringTokenizer tokens = new StringTokenizer(token, ".", true); pathExpressionParser.start(q); while (tokens.hasMoreTokens()) { pathExpressionParser.token(tokens.nextToken(), q); } pathExpressionParser.end(q); if (pathExpressionParser.isCollectionValued()) { openExpression(q, ""); appendToken(q, pathExpressionParser.getCollectionSubquery(q.getEnabledFilters())); closeExpression(q, ""); // this is ugly here, but needed because its a subquery q.addQuerySpaces( q.getCollectionPersister(pathExpressionParser.getCollectionRole()).getCollectionSpaces()); } else { if (pathExpressionParser.isExpectingCollectionIndex()) { expectingIndex++; } else { addJoin(pathExpressionParser.getWhereJoin(), q); appendToken(q, pathExpressionParser.getWhereColumn()); } } }
void appendToken(QueryTranslatorImpl q, String token) { if (expectingIndex > 0) { pathExpressionParser.setLastCollectionElementIndexValue(token); } else { q.appendWhereToken(token); } }
private void addJoin(JoinSequence joinSequence, QueryTranslatorImpl q) throws QueryException { // JoinFragment fromClause = q.createJoinFragment(true); // fromClause.addJoins( join.toJoinFragment().toFromFragmentString(), StringHelper.EMPTY_STRING // ); q.addFromJoinOnly(pathExpressionParser.getName(), joinSequence); try { addToCurrentJoin( joinSequence.toJoinFragment(q.getEnabledFilters(), true).toWhereFragmentString()); } catch (MappingException me) { throw new QueryException(me); } }
public void end(QueryTranslatorImpl q) throws QueryException { if (expectingPathContinuation) { expectingPathContinuation = false; PathExpressionParser.CollectionElement element = pathExpressionParser.lastCollectionElement(); if (element.elementColumns.length != 1) { throw new QueryException("path expression ended in composite collection element"); } appendToken(q, element.elementColumns[0]); addToCurrentJoin(element); } token(")", q); }
private String getElementName( PathExpressionParser.CollectionElement element, QueryTranslatorImpl q) throws QueryException { String name; if (element.isOneToMany) { name = element.alias; } else { Type type = element.elementType; if (type.isEntityType()) { // ie. a many-to-many String entityName = ((EntityType) type).getAssociatedEntityName(); name = pathExpressionParser.continueFromManyToMany(entityName, element.elementColumns, q); } else { throw new QueryException("illegally dereferenced collection element"); } } return name; }
private void preprocess(String token, QueryTranslatorImpl q) throws QueryException { // ugly hack for cases like "elements(foo.bar.collection)" // (multi-part path expression ending in elements or indices) String[] tokens = StringHelper.split(".", token, true); if (tokens.length > 5 && (CollectionPropertyNames.COLLECTION_ELEMENTS.equals(tokens[tokens.length - 1]) || CollectionPropertyNames.COLLECTION_INDICES.equals(tokens[tokens.length - 1]))) { pathExpressionParser.start(q); for (int i = 0; i < tokens.length - 3; i++) { pathExpressionParser.token(tokens[i], q); } pathExpressionParser.token(null, q); pathExpressionParser.end(q); addJoin(pathExpressionParser.getWhereJoin(), q); pathExpressionParser.ignoreInitialJoin(); } }
private boolean continuePathExpression(String token, QueryTranslatorImpl q) throws QueryException { expectingPathContinuation = false; PathExpressionParser.CollectionElement element = pathExpressionParser.lastCollectionElement(); if (token.startsWith(".")) { // the path expression continues after a ] doPathExpression(getElementName(element, q) + token, q); // careful with this! addToCurrentJoin(element); return true; // NOTE: EARLY EXIT! } else { // the path expression ends at the ] if (element.elementColumns.length != 1) { throw new QueryException("path expression ended in composite collection element"); } appendToken(q, element.elementColumns[0]); addToCurrentJoin(element); return false; } }
{ pathExpressionParser = new PathExpressionParser(); pathExpressionParser.setUseThetaStyleJoin( true); // Need this, since join condition can appear inside parens! }