001: /*
002: * $Header: /export/home/cvsroot/MyPersonalizerRepository/MyPersonalizer/Subsystems/Kernel/Sources/es/udc/mypersonalizer/kernel/model/query/executor/sql/SelectIdsMetaPropertyVisitor.java,v 1.1.1.1 2004/03/25 12:08:37 fbellas Exp $
003: * $Revision: 1.1.1.1 $
004: * $Date: 2004/03/25 12:08:37 $
005: *
006: * =============================================================================
007: *
008: * Copyright (c) 2003, The MyPersonalizer Development Group
009: * (http://www.tic.udc.es/~fbellas/mypersonalizer/index.html) at
010: * University Of A Coruņa
011: * All rights reserved.
012: *
013: * Redistribution and use in source and binary forms, with or without
014: * modification, are permitted provided that the following conditions are met:
015: *
016: * - Redistributions of source code must retain the above copyright notice,
017: * this list of conditions and the following disclaimer.
018: *
019: * - Redistributions in binary form must reproduce the above copyright notice,
020: * this list of conditions and the following disclaimer in the documentation
021: * and/or other materials provided with the distribution.
022: *
023: * - Neither the name of the University Of A Coruņa nor the names of its
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
028: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
029: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
030: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
031: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
032: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
033: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
034: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
035: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
036: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
037: * POSSIBILITY OF SUCH DAMAGE.
038: *
039: */
040: package es.udc.mypersonalizer.kernel.model.query.executor.sql;
041:
042: import java.util.ArrayList;
043: import java.util.HashSet;
044: import java.util.Iterator;
045: import java.util.List;
046: import java.util.Set;
047:
048: import es.udc.mypersonalizer.kernel.log.Log;
049: import es.udc.mypersonalizer.kernel.log.LogManager;
050: import es.udc.mypersonalizer.kernel.log.LogNamingConventions;
051: import es.udc.mypersonalizer.kernel.model.annotators.sql.SQLPersistenceTypeAnnotationHelper;
052: import es.udc.mypersonalizer.kernel.model.metainfo.MetaCompoundProperty;
053: import es.udc.mypersonalizer.kernel.model.metainfo.MetaProperty;
054: import es.udc.mypersonalizer.kernel.model.metainfo.MetaPropertyNotFoundException;
055: import es.udc.mypersonalizer.kernel.model.metainfo.MetaSimpleProperty;
056: import es.udc.mypersonalizer.kernel.model.query.ast.Query;
057: import es.udc.mypersonalizer.kernel.model.query.ast.Step;
058: import es.udc.mypersonalizer.kernel.model.query.ast.expr.ContainsFunctionExpression;
059: import es.udc.mypersonalizer.kernel.model.query.ast.expr.EqualsExpression;
060: import es.udc.mypersonalizer.kernel.model.query.ast.expr.Expression;
061: import es.udc.mypersonalizer.kernel.model.query.ast.expr.ExpressionVisitor;
062: import es.udc.mypersonalizer.kernel.model.query.ast.expr.GreaterOrEqualExpression;
063: import es.udc.mypersonalizer.kernel.model.query.ast.expr.GreaterThanExpression;
064: import es.udc.mypersonalizer.kernel.model.query.ast.expr.LesserOrEqualExpression;
065: import es.udc.mypersonalizer.kernel.model.query.ast.expr.LesserThanExpression;
066: import es.udc.mypersonalizer.kernel.model.query.ast.expr.LiteralBooleanExpression;
067: import es.udc.mypersonalizer.kernel.model.query.ast.expr.LiteralNumericExpression;
068: import es.udc.mypersonalizer.kernel.model.query.ast.expr.LiteralStringExpression;
069: import es.udc.mypersonalizer.kernel.model.query.ast.expr.LogicalAndExpression;
070: import es.udc.mypersonalizer.kernel.model.query.ast.expr.LogicalOrExpression;
071: import es.udc.mypersonalizer.kernel.model.query.ast.expr.NotEqualsExpression;
072: import es.udc.mypersonalizer.kernel.model.query.ast.expr.StartsWithFunctionExpression;
073: import es.udc.mypersonalizer.kernel.model.query.ast.expr.StepExpression;
074: import es.udc.mypersonalizer.kernel.model.query.ast.expr.PropertyListExpression;
075: import es.udc.mypersonalizer.kernel.model.query.virtualmetainfo.LinkMetaPropertyAnnotationHelper;
076: import es.udc.mypersonalizer.kernel.model.query.virtualmetainfo.VirtualMetaPropertyAnnotationHelper;
077: import es.udc.mypersonalizer.kernel.model.repository.sql.config.DatabaseConventionsConfigManager;
078: import es.udc.mypersonalizer.kernel.util.exceptions.InternalErrorException;
079: import es.udc.mypersonalizer.kernel.util.exceptions.VisitorException;
080:
081: /**
082: * This visitor incrementally builds an SQL query to retrieve the property
083: * identifiers of the result root properties.
084: *
085: * @author Abel Muinho
086: * @since 1.0
087: */
088: public class SelectIdsMetaPropertyVisitor implements
089: MetaProperty.Visitor, ExpressionVisitor {
090:
091: private boolean targetTableIsURITable;
092:
093: private static final Log log = LogManager
094: .getLog(LogNamingConventions.MYPERSONALIZER);
095:
096: /* Constants for building SQL queries. */
097: private static final String WHERE_STRING = " WHERE ";
098:
099: private static final String COMMA_STRING = ", ";
100:
101: private static final String AND_STRING = " AND ";
102:
103: private static final String OR_STRING = " OR ";
104:
105: private static final String NOT_STRING = " NOT ";
106:
107: private static final String GREATER_THAN_STRING = " > ";
108:
109: private static final String GREATER_OR_EQUAL_STRING = ">=";
110:
111: private static final String LESSER_THAN_STRING = " < ";
112:
113: private static final String LESSER_OR_EQUAL_STRING = "<=";
114:
115: private static final String EQUAL_STRING = " = ";
116:
117: private static final String NOT_EQUAL_STRING = " <> ";
118:
119: private static final String RPAREN_STRING = ")";
120:
121: private static final String LPAREN_STRING = "(";
122:
123: private static final String PARAMETER_STRING = "?";
124:
125: private static final String LIKE_STRING = " LIKE ";
126:
127: private static final char ESCAPE_CHAR = '#';
128:
129: private static final String ESCAPE_STRING = " ESCAPE '"
130: + ESCAPE_CHAR + "' ";
131:
132: private static final String FROM_STRING = " FROM ";
133:
134: private static final String DOT_STRING = ".";
135:
136: private static final String AS_STRING = " AS ";
137:
138: private static final String SELECT_STRING = "SELECT ";
139:
140: private static final String DISTINCT_STRING = "DISTINCT ";
141:
142: private static final String ORDER_BY_STRING = " ORDER BY ";
143:
144: private static final String GROUP_BY_STRING = " GROUP BY ";
145:
146: private static String PROPERTY_ID_COLUMN = null;
147:
148: private static String GENERATED_ID_COLUMN = null;
149:
150: private static String LOGIN_COLUMN = null;
151:
152: /** "Unique" name for the order by column alias. */
153: private static final String ORDER_BY_COLUMN_NAME = "obc658amv";
154:
155: private String resultTable = null;
156:
157: private String orderByTable = null;
158:
159: private String orderByColumn = null;
160:
161: private Set tables = new HashSet();
162:
163: private Set joinConditions = new HashSet();
164:
165: private List whereConditions = new ArrayList();
166:
167: /** Parameter values to be used in the SQL query, in the right order. */
168: private List parameters = new ArrayList();
169:
170: /** A temporary queue used for sorting the parameters. */
171: private List pendingParametersQueue = new ArrayList();
172:
173: private MetaProperty previousMetaProperty = null;
174:
175: private MetaProperty targetMetaProperty = null;
176:
177: /**
178: * Creates a new visitor.
179: *
180: * @throws InternalErrorException
181: * if errors occur while trying to retrieve values from the
182: * configuration.
183: */
184: public SelectIdsMetaPropertyVisitor() throws InternalErrorException {
185:
186: if (PROPERTY_ID_COLUMN == null) {
187: PROPERTY_ID_COLUMN = DatabaseConventionsConfigManager
188: .getConfig().getPropertyIdentifierColumn();
189: }
190: if (GENERATED_ID_COLUMN == null) {
191: GENERATED_ID_COLUMN = DatabaseConventionsConfigManager
192: .getConfig().getGeneratedIdentifierColumn();
193: }
194: if (LOGIN_COLUMN == null) {
195: LOGIN_COLUMN = DatabaseConventionsConfigManager.getConfig()
196: .getLoginColumn();
197: }
198:
199: }
200:
201: /**
202: * Prepares the query for generation.
203: *
204: * @param query
205: * the <code>Query</code> to be prepared.
206: * @throws InternalErrorException
207: * if errors occur while accessing the data from the
208: * configuration.
209: */
210: public void buildQuery(Query query) throws InternalErrorException {
211: MetaProperty metaProperty = null;
212:
213: targetMetaProperty = ((Step) query.getReturnClause().get(
214: query.getReturnClause().size() - 1)).getMetaProperty();
215: resultTable = SQLPersistenceTypeAnnotationHelper
216: .getTableNameAnnotation(targetMetaProperty);
217: tables.add(resultTable);
218:
219: try {
220: StepExpression stepExpression = new StepExpression();
221: stepExpression.setSteps(query.getReturnClause());
222: stepExpression.accept(this );
223:
224: if (query.getOrderByClause() != null) {
225: previousMetaProperty = null;
226: Iterator orderByIt = query.getOrderByClause()
227: .iterator();
228: while (orderByIt.hasNext()) {
229: Step step = (Step) orderByIt.next();
230: metaProperty = step.getMetaProperty();
231: metaProperty.accept(this );
232: if (step.getExpression() != null) {
233: whereConditions.add(step.getExpression()
234: .accept(this ));
235: }
236: }
237:
238: int orderSteps = query.getOrderByClause().size();
239: Step lastOrderStep = (Step) query.getOrderByClause()
240: .get(orderSteps - 1);
241: MetaProperty lastOrderMetaProperty = lastOrderStep
242: .getMetaProperty();
243:
244: orderByTable = SQLPersistenceTypeAnnotationHelper
245: .getTableNameAnnotation(lastOrderMetaProperty);
246: tables.add(orderByTable);
247: orderByColumn = SQLPersistenceTypeAnnotationHelper
248: .getColumnNameAnnotation(lastOrderMetaProperty);
249: }
250: } catch (VisitorException e) {
251: throw new InternalErrorException(e);
252: }
253: targetTableIsURITable = SQLQueryExecutorHelper
254: .isUserRegistrationInformationTable(resultTable);
255: }
256:
257: /**
258: * Obtains the currently built query <code>SELECT</code> ing just the
259: * property identifier column.
260: *
261: * @return the SQL query with parameters suitable for use in a <code>PreparedStatement</code>.
262: */
263: public String getSqlForPropertyIds() {
264: StringBuffer result = new StringBuffer(255);
265:
266: /* SELECT */
267: result.append(SELECT_STRING).append(DISTINCT_STRING).append(
268: resultTable).append(DOT_STRING).append("* ");
269: if (orderByTable != null && orderByColumn != null) {
270: result.append(COMMA_STRING).append(orderByTable).append(
271: DOT_STRING).append(orderByColumn).append(AS_STRING)
272: .append(ORDER_BY_COLUMN_NAME);
273: }
274: /* FROM */
275: result.append(FROM_STRING);
276: Iterator itTables = tables.iterator();
277: while (itTables.hasNext()) {
278: result.append((String) itTables.next());
279: if (itTables.hasNext()) {
280: result.append(COMMA_STRING);
281: }
282: }
283: /* WHERE */
284: if (joinConditions.size() > 0 || whereConditions.size() > 0) {
285: result.append(WHERE_STRING);
286:
287: Iterator itJoins = joinConditions.iterator();
288: while (itJoins.hasNext()) {
289: result.append(LPAREN_STRING).append(
290: (String) itJoins.next()).append(RPAREN_STRING);
291: if (itJoins.hasNext()) {
292: result.append(AND_STRING);
293: }
294: }
295: if (joinConditions.size() > 0 && whereConditions.size() > 0) {
296: result.append(AND_STRING);
297: }
298: Iterator itWhere = whereConditions.iterator();
299: while (itWhere.hasNext()) {
300: result.append(LPAREN_STRING).append(
301: (String) itWhere.next()).append(RPAREN_STRING);
302: if (itWhere.hasNext()) {
303: result.append(AND_STRING);
304: }
305: }
306: }
307:
308: /* ORDER BY */
309: boolean isOrdered = orderByTable != null
310: && orderByColumn != null;
311: boolean isTargetMultivalued = targetMetaProperty
312: .isMultiValued();
313: result.append(ORDER_BY_STRING);
314: if (isTargetMultivalued || isOrdered) {
315: /* ORDER BY the foreign key, if multivalued. */
316: if (isTargetMultivalued) {
317: result.append(resultTable).append(DOT_STRING);
318: if (targetTableIsURITable) {
319: result.append(LOGIN_COLUMN);
320: } else {
321: result.append(PROPERTY_ID_COLUMN);
322: }
323: /* Separate from other fields. */
324: result.append(COMMA_STRING);
325: if (!isOrdered) {
326: /* Use generated id to keep document order */
327: result.append(GENERATED_ID_COLUMN);
328: }
329: }
330: if (isOrdered) {
331: result.append(ORDER_BY_COLUMN_NAME);
332: }
333: } else {
334: /*
335: * If it is not multivalued, not ordered, use primary key to keep
336: * "document order" (primary key order)
337: */
338: result.append(resultTable).append(DOT_STRING);
339: if (targetTableIsURITable) {
340: result.append(LOGIN_COLUMN);
341: } else {
342: result.append(PROPERTY_ID_COLUMN);
343: }
344: }
345:
346: log.write("Generated SQL: " + result.toString(), null,
347: SelectIdsMetaPropertyVisitor.class);
348: log.write("Parameters: " + parameters.toString(), null,
349: SelectIdsMetaPropertyVisitor.class);
350: return result.toString();
351: }
352:
353: /**
354: * Obtains the list of parameters to be used with the generated SQL.
355: *
356: * @return the list of parameters.
357: */
358: public List getParameters() {
359: return parameters;
360: }
361:
362: /*
363: * ------------------------------------------------------------------------
364: * Implementation of the MetaProperty.Visitor interface.
365: */
366:
367: public Object visitMetaSimpleProperty(
368: MetaSimpleProperty metaProperty) {
369:
370: /*
371: * SimpleProperties can't be root of MetaServices and only are stored
372: * in a table if they are multivalued.
373: */
374: if (metaProperty.isMultiValued()) {
375: joinConditions.add(buildJoinCondition(previousMetaProperty,
376: metaProperty));
377: }
378: return null;
379: }
380:
381: public Object visitMetaCompoundProperty(
382: MetaCompoundProperty metaProperty) throws VisitorException {
383:
384: boolean isVirtual = VirtualMetaPropertyAnnotationHelper
385: .isVirtual(metaProperty);
386:
387: /*
388: * For tables beyond the first one, add a join clause.
389: */
390: if (previousMetaProperty != null) {
391: /* At least one previously visited metaproperty, JOIN required. */
392: if (!isVirtual) {
393: /* Handle non virtual properties. */
394: String joinCondition = buildJoinCondition(
395: previousMetaProperty, metaProperty);
396: joinConditions.add(joinCondition);
397: } else {
398: /* Handle virtual properties. */
399: /* TODO: Refactor using the command pattern if grows. */
400: /* TODO: only valid for the metaservice-link */
401: visitVirtualLinkMetaProperty(metaProperty);
402: }
403: } else {
404: /* This is the first metaproperty. */
405: /* Add its table to the result. */
406: tables.add(SQLPersistenceTypeAnnotationHelper
407: .getTableNameAnnotation(metaProperty));
408: }
409: previousMetaProperty = metaProperty;
410:
411: return null;
412: }
413:
414: /**
415: * @param metaProperty
416: * @throws VisitorException
417: */
418: protected void visitVirtualLinkMetaProperty(
419: MetaCompoundProperty metaProperty) throws VisitorException {
420: MetaProperty sourceMetaProperty;
421: try {
422: sourceMetaProperty = previousMetaProperty
423: .findMetaProperty(LinkMetaPropertyAnnotationHelper
424: .getSourceProperty(metaProperty));
425: } catch (MetaPropertyNotFoundException e) {
426: throw new VisitorException(e);
427: }
428:
429: if (sourceMetaProperty.isMultiValued()) {
430: /* Need to join with the parent. */
431: joinConditions.add(buildJoinCondition(previousMetaProperty,
432: sourceMetaProperty));
433: }
434:
435: String joinCondition = buildLinkJoinCondition(
436: sourceMetaProperty, metaProperty);
437:
438: /*
439: * FIX for BUG0002,
440: * Avoid adding new parameters if the join condition has been
441: * already used.
442: *
443: * @see SQLQueryExecutorDelegateTest#testBug0002
444: */
445: if (!joinConditions.contains(joinCondition)) {
446: joinConditions.add(joinCondition);
447: if (!LinkMetaPropertyAnnotationHelper
448: .isInternalReference(metaProperty)) {
449: String sourceTable = SQLPersistenceTypeAnnotationHelper
450: .getTableNameAnnotation(sourceMetaProperty);
451: joinConditions.add(sourceTable + DOT_STRING
452: + "serviceId = ?");
453: parameters.add(LinkMetaPropertyAnnotationHelper
454: .getTargetMetaService(metaProperty));
455: }
456: }
457: }
458:
459: /*
460: * ------------------------------------------------------------------------
461: * Implementation of the MetaProperty.Visitor interface.
462: */
463:
464: public Object visit(LogicalAndExpression e) throws VisitorException {
465: return LPAREN_STRING + e.getLHS().accept(this ) + RPAREN_STRING
466: + AND_STRING + LPAREN_STRING + e.getRHS().accept(this )
467: + RPAREN_STRING;
468: }
469:
470: public Object visit(LogicalOrExpression e) throws VisitorException {
471: return LPAREN_STRING + e.getLHS().accept(this ) + RPAREN_STRING
472: + OR_STRING + LPAREN_STRING + e.getRHS().accept(this )
473: + RPAREN_STRING;
474: }
475:
476: public Object visit(EqualsExpression e) throws VisitorException {
477: return e.getLHS().accept(this ) + EQUAL_STRING
478: + e.getRHS().accept(this );
479: }
480:
481: // @see
482: // es.udc.mypersonalizer.kernel.model.query.ast.expr.ExpressionVisitor#visit(es.udc.mypersonalizer.kernel.model.query.ast.expr.NotEqualsExpression)
483: public Object visit(NotEqualsExpression e) throws VisitorException {
484: return e.getLHS().accept(this ) + NOT_EQUAL_STRING
485: + e.getRHS().accept(this );
486: }
487:
488: public Object visit(LiteralBooleanExpression e) {
489: enqueueParameterValue(e.getValue());
490: return PARAMETER_STRING;
491: }
492:
493: public Object visit(LiteralNumericExpression e) {
494: enqueueParameterValue(e.getValue());
495: return PARAMETER_STRING;
496: }
497:
498: public Object visit(LiteralStringExpression e) {
499: enqueueParameterValue(e.getValue());
500: return PARAMETER_STRING;
501: }
502:
503: public Object visit(PropertyListExpression e) {
504: /* This call is not possible. */
505: throw new UnsupportedOperationException();
506: }
507:
508: public Object visit(StepExpression e) throws VisitorException {
509: /* Backup current state as "old" */
510: MetaProperty oldPreviousMetaProperty = this .previousMetaProperty;
511:
512: MetaProperty metaProperty = null;
513: Iterator it = e.getSteps().iterator();
514: while (it.hasNext()) {
515: Step step = (Step) it.next();
516: metaProperty = step.getMetaProperty();
517: metaProperty.accept(this );
518: if (step.getExpression() != null) {
519: /* Create temporary space for the paramters. */
520: pendingParametersQueue.add(0, new ArrayList());
521: whereConditions.add(step.getExpression().accept(this ));
522: parameters.addAll((List) pendingParametersQueue.get(0));
523: /* We are done with our holding space. */
524: pendingParametersQueue.remove(0);
525: }
526: }
527: String result = SQLPersistenceTypeAnnotationHelper
528: .getTableNameAnnotation(metaProperty)
529: + DOT_STRING
530: + SQLPersistenceTypeAnnotationHelper
531: .getColumnNameAnnotation(metaProperty);
532: /* Restore backed-up state. */
533: previousMetaProperty = oldPreviousMetaProperty;
534:
535: return result;
536: }
537:
538: public Object visit(ContainsFunctionExpression expression)
539: throws VisitorException {
540: Expression container = expression.getArguments()[0];
541: Expression contained = expression.getArguments()[1];
542: if (contained instanceof LiteralStringExpression) {
543: LiteralStringExpression stringExpr = (LiteralStringExpression) contained;
544: String value = escapeLike(stringExpr.getString());
545:
546: stringExpr.setValue('%' + value + '%');
547: return container.accept(this ) + LIKE_STRING
548: + stringExpr.accept(this ) + ESCAPE_STRING;
549: } else {
550: throw new VisitorException("Second argument for 'contains'"
551: + " must be a literal String");
552: }
553: }
554:
555: public Object visit(StartsWithFunctionExpression expression)
556: throws VisitorException {
557: Expression container = expression.getArguments()[0];
558: Expression contained = expression.getArguments()[1];
559: if (contained instanceof LiteralStringExpression) {
560: LiteralStringExpression stringExpr = (LiteralStringExpression) contained;
561: String value = escapeLike(stringExpr.getString());
562:
563: stringExpr.setValue(value + '%');
564: return container.accept(this ) + LIKE_STRING
565: + stringExpr.accept(this ) + ESCAPE_STRING;
566: } else {
567: throw new VisitorException(
568: "Second argument for 'starts-with'"
569: + " must be a literal String");
570: }
571: }
572:
573: public Object visit(GreaterThanExpression e)
574: throws VisitorException {
575: return e.getLHS().accept(this ) + GREATER_THAN_STRING
576: + e.getRHS().accept(this );
577: }
578:
579: public Object visit(LesserThanExpression e) throws VisitorException {
580: return e.getLHS().accept(this ) + LESSER_THAN_STRING
581: + e.getRHS().accept(this );
582:
583: }
584:
585: public Object visit(GreaterOrEqualExpression e)
586: throws VisitorException {
587: return e.getLHS().accept(this ) + GREATER_OR_EQUAL_STRING
588: + e.getRHS().accept(this );
589: }
590:
591: public Object visit(LesserOrEqualExpression e)
592: throws VisitorException {
593: return e.getLHS().accept(this ) + LESSER_OR_EQUAL_STRING
594: + e.getRHS().accept(this );
595: }
596:
597: /**
598: * Escapes the string constant to be used as a literal in the RHS of a SQL
599: * LIKE expression.
600: *
601: * @param sql
602: * the string to escape.
603: * @return the escaped string.
604: */
605: private String escapeLike(String sql) {
606: return sql.replaceAll("(_|%|" + ESCAPE_CHAR + ")", ESCAPE_CHAR
607: + "$1");
608: }
609:
610: /**
611: * Adds a parameter's value to the temporary queue.
612: *
613: * @param value
614: * the value of the parameter.
615: */
616: private void enqueueParameterValue(Object value) {
617: ((List) pendingParametersQueue.get(0)).add(value);
618: }
619:
620: /**
621: * Builds the join condition for "real" properties.
622: *
623: * @param parent
624: * the parent property.
625: * @param child
626: * the child property.
627: * @return the join condition as SQL.
628: */
629: private String buildJoinCondition(MetaProperty parent,
630: MetaProperty child) {
631: String previousTable = SQLPersistenceTypeAnnotationHelper
632: .getTableNameAnnotation(parent);
633: String previousTableKey = SQLPersistenceTypeAnnotationHelper
634: .getIdColumnAnnotation(parent);
635: String currentTable = SQLPersistenceTypeAnnotationHelper
636: .getTableNameAnnotation(child);
637: String currentTableReference = SQLPersistenceTypeAnnotationHelper
638: .getFKColumnAnnotation(child);
639: /* Make sure that our tables are in the FROM clause. */
640: tables.add(previousTable);
641: tables.add(currentTable);
642: return previousTable + DOT_STRING + previousTableKey
643: + EQUAL_STRING + currentTable + DOT_STRING
644: + currentTableReference;
645: }
646:
647: /**
648: * Builds the join condition for "virtual" link properties.
649: *
650: * @param parent
651: * the parent property.
652: * @param child
653: * the child property.
654: * @return the join condition as SQL.
655: */
656: private String buildLinkJoinCondition(MetaProperty parent,
657: MetaProperty child) {
658: String previousTable = SQLPersistenceTypeAnnotationHelper
659: .getTableNameAnnotation(parent);
660: String previousTableReference = SQLPersistenceTypeAnnotationHelper
661: .getColumnNameAnnotation(parent);
662: String currentTable = SQLPersistenceTypeAnnotationHelper
663: .getTableNameAnnotation(child);
664: String currentTableKey = SQLPersistenceTypeAnnotationHelper
665: .getFKColumnAnnotation(child);
666: /* Make sure that our tables are in the FROM clause. */
667: tables.add(previousTable);
668: tables.add(currentTable);
669: return previousTable + DOT_STRING + previousTableReference
670: + EQUAL_STRING + currentTable + DOT_STRING
671: + currentTableKey;
672: }
673: }
|