001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free Software Foundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.amber.expr;
030:
031: import com.caucho.amber.query.FromItem;
032: import com.caucho.amber.query.QueryParser;
033: import com.caucho.amber.table.ForeignColumn;
034: import com.caucho.amber.table.LinkColumns;
035: import com.caucho.util.CharBuffer;
036:
037: /**
038: * Joins two tables as "a.children".
039: */
040: public class OneToManyJoinExpr extends JoinExpr {
041: private LinkColumns _linkColumns;
042:
043: private FromItem _sourceFromItem;
044: private FromItem _targetFromItem;
045:
046: /**
047: * Creates the expr.
048: */
049: public OneToManyJoinExpr(LinkColumns linkColumns, FromItem source,
050: FromItem target) {
051: _linkColumns = linkColumns;
052:
053: _sourceFromItem = source;
054: _targetFromItem = target;
055:
056: if (source == null || target == null)
057: throw new NullPointerException();
058: }
059:
060: /**
061: * Returns true for a boolean expression.
062: */
063: public boolean isBoolean() {
064: return true;
065: }
066:
067: /**
068: * Binds the expression as a select item.
069: */
070: public AmberExpr bindSelect(QueryParser parser) {
071: return this ;
072: }
073:
074: /**
075: * Binds the link to the from item.
076: */
077: public boolean bindToFromItem() {
078: if (_sourceFromItem.getJoinExpr() == null
079: || _sourceFromItem.getJoinExpr().equals(this )) {
080: _sourceFromItem.setJoinExpr(this );
081: return true;
082: }
083:
084: ManyToOneJoinExpr manyToOne = new ManyToOneJoinExpr(
085: _linkColumns, _sourceFromItem, _targetFromItem);
086:
087: if (_targetFromItem.getJoinExpr() == null
088: || _targetFromItem.getJoinExpr().equals(manyToOne)) {
089: _targetFromItem.setJoinExpr(manyToOne);
090:
091: return true;
092: } else
093: return false;
094: }
095:
096: /**
097: * Returns the target join clause.
098: */
099: public FromItem getJoinTarget() {
100: return _targetFromItem;
101: }
102:
103: /**
104: * Returns the parent join clause, i.e. the first in the FROM order.
105: * <pre>
106: * FROM o, o.children
107: * <pre>
108: */
109: public FromItem getJoinParent() {
110: return _targetFromItem;
111: }
112:
113: /**
114: * Returns the id expr with the joined expression.
115: */
116: public AmberExpr replace(KeyColumnExpr id) {
117: PathExpr parent = id.getParent();
118:
119: if (parent.getChildFromItem() != _targetFromItem)
120: return id;
121:
122: ForeignColumn sourceColumn = _linkColumns.getSourceColumn(id
123: .getColumn());
124:
125: if (sourceColumn == null)
126: throw new IllegalStateException(id.getColumn().getName());
127:
128: return new ColumnExpr(_sourceFromItem.getIdExpr(), sourceColumn);
129: }
130:
131: /**
132: * Returns the id expr with the joined expression.
133: */
134: public AmberExpr replace(IdExpr id) {
135: return id;
136: }
137:
138: /**
139: * Returns the where clause once the parent is removed
140: */
141: public AmberExpr getWhere() {
142: /*
143: * The code is partially correct, but the is null test isn't
144: * needed in many cases, so should probably test the actual
145: * expression
146: AndExpr and = new AndExpr();
147: IdExpr id = new IdExpr(_sourceFromItem);
148:
149: for (ForeignColumn column : _linkColumns.getColumns()) {
150: and.add(new UnaryExpr(QueryParser.NOT_NULL,
151: new ColumnExpr(id, column)));
152: }
153:
154: return and.getSingle();
155: */
156:
157: return null;
158: }
159:
160: /**
161: * Generates the where expression.
162: */
163: public void generateWhere(CharBuffer cb) {
164: cb.append(_linkColumns.generateWhere(_sourceFromItem.getName(),
165: _targetFromItem.getName()));
166: }
167:
168: /**
169: * Generates the (update) where expression.
170: */
171: public void generateUpdateWhere(CharBuffer cb) {
172: generateWhere(cb);
173: }
174:
175: /**
176: * Generates the having expression.
177: */
178: public void generateHaving(CharBuffer cb) {
179: generateWhere(cb);
180: }
181:
182: /**
183: * Generates the where expression.
184: */
185: public void generateJoin(CharBuffer cb) {
186: cb.append(_linkColumns.generateJoin(_sourceFromItem.getName(),
187: _targetFromItem.getName()));
188: }
189:
190: /**
191: * Test for equality.
192: */
193: public boolean equals(Object o) {
194: if (!(o instanceof OneToManyJoinExpr))
195: return false;
196:
197: OneToManyJoinExpr joinExpr = (OneToManyJoinExpr) o;
198:
199: return (_linkColumns.equals(joinExpr._linkColumns)
200: && _targetFromItem.equals(joinExpr._targetFromItem) && _sourceFromItem
201: .equals(joinExpr._sourceFromItem));
202: }
203:
204: public String toString() {
205: return ("OneToManyJoinExpr[" + _linkColumns + ","
206: + _targetFromItem + "," + _sourceFromItem + "]");
207: }
208: }
|