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: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.amber.expr;
031:
032: import com.caucho.amber.query.FromItem;
033: import com.caucho.amber.query.QueryParser;
034: import com.caucho.amber.table.LinkColumns;
035: import com.caucho.amber.table.Table;
036: import com.caucho.amber.type.RelatedType;
037: import com.caucho.amber.type.Type;
038: import com.caucho.util.CharBuffer;
039:
040: /**
041: * Link expression to a new table
042: */
043: public class ManyToOneExpr extends AbstractPathExpr {
044: private PathExpr _parent;
045:
046: private LinkColumns _linkColumns;
047:
048: private FromItem _fromItem;
049: private FromItem _childFromItem;
050:
051: /**
052: * Creates a new unbound id expression.
053: */
054: public ManyToOneExpr(PathExpr parent, LinkColumns linkColumns) {
055: _parent = parent;
056: _linkColumns = linkColumns;
057: }
058:
059: /**
060: * Returns the entity class.
061: */
062: public RelatedType getTargetType() {
063: return _linkColumns.getTargetTable().getType();
064: }
065:
066: /**
067: * Returns the entity class.
068: */
069: public Type getType() {
070: return getTargetType();
071: }
072:
073: /**
074: * Binds the expression as a select item.
075: */
076: public AmberExpr bindSelect(QueryParser parser) {
077: _fromItem = _parent.bindSubPath(parser);
078:
079: return this ;
080: }
081:
082: /**
083: * Return the parent from item.
084: */
085: public FromItem getFromItem() {
086: return _fromItem;
087: }
088:
089: /**
090: * Returns the link columns.
091: */
092: public LinkColumns getLinkColumns() {
093: return _linkColumns;
094: }
095:
096: /**
097: * Return the child from item.
098: */
099: public FromItem getChildFromItem() {
100: return _childFromItem;
101: }
102:
103: /**
104: * Binds the expression as a subpath.
105: */
106: public FromItem bindSubPath(QueryParser parser) {
107: if (_childFromItem != null)
108: return _childFromItem;
109:
110: ManyToOneExpr pathExpr = (ManyToOneExpr) parser.addPath(this );
111:
112: if (pathExpr != this ) {
113: _fromItem = pathExpr._fromItem;
114: _childFromItem = pathExpr._childFromItem;
115:
116: return _childFromItem;
117: }
118:
119: // XXX: handled at constructor?
120: _parent = _parent.bindSelect(parser, null);
121:
122: bindSelect(parser, parser.createTableName());
123:
124: return _childFromItem;
125: }
126:
127: /**
128: * Binds the expression as a select item.
129: */
130: public PathExpr bindSelect(QueryParser parser, String id) {
131: if (_childFromItem != null)
132: return this ;
133:
134: if (_fromItem == null)
135: _fromItem = _parent.bindSubPath(parser);
136:
137: Table targetTable = _linkColumns.getTargetTable();
138: _childFromItem = parser.addFromItem(targetTable, id);
139:
140: JoinExpr joinExpr;
141: joinExpr = new ManyToOneJoinExpr(_linkColumns, _fromItem,
142: _childFromItem);
143:
144: _childFromItem.setJoinExpr(joinExpr);
145:
146: return this ;
147: }
148:
149: /**
150: * Returns true if the expression uses the from item.
151: */
152: public boolean usesFrom(FromItem from, int type, boolean isNot) {
153: return (_childFromItem == from && type == IS_INNER_JOIN
154: || _fromItem == from || _parent.usesFrom(from, type));
155: }
156:
157: /**
158: * Returns true if the item is forced to exist by the parent
159: */
160: @Override
161: public boolean exists(FromItem from) {
162: return (_fromItem == from && _parent.exists());
163: }
164:
165: /**
166: * Returns the table.
167: */
168: /*
169: public Table getTable()
170: {
171: if (_childFromItem != null)
172: return _childFromItem.getTable();
173: else if (_fromItem != null)
174: return _fromItem.getTable();
175: else
176: return _parent.getTable();
177: }
178: */
179:
180: /**
181: * Generates the where expression.
182: */
183: public void generateMatchArgWhere(CharBuffer cb) {
184: if (_fromItem != null) {
185: cb.append(_linkColumns.generateMatchArgSQL(_fromItem
186: .getName()));
187: } else {
188: cb.append(_linkColumns.generateMatchArgSQL(_parent
189: .getChildFromItem().getName()));
190: }
191: }
192:
193: /**
194: * Generates the where expression.
195: */
196: public void generateWhere(CharBuffer cb) {
197: generateInternalWhere(cb, true);
198: }
199:
200: /**
201: * Generates the (update) where expression.
202: */
203: public void generateUpdateWhere(CharBuffer cb) {
204: generateInternalWhere(cb, false);
205: }
206:
207: /**
208: * Generates the select expression.
209: */
210: // ejb/06q4
211: public void generateSelect(CharBuffer cb) {
212: String tableName;
213:
214: if (_fromItem != null)
215: tableName = _fromItem.getName();
216: else
217: tableName = _parent.getChildFromItem().getName();
218:
219: cb.append(_linkColumns.generateSelectSQL(tableName));
220: }
221:
222: /**
223: * Returns the parent.
224: */
225: public PathExpr getParent() {
226: return _parent;
227: }
228:
229: public int hashCode() {
230: return 65521 * _parent.hashCode() + _linkColumns.hashCode();
231: }
232:
233: public boolean equals(Object o) {
234: if (o == null || !getClass().equals(o.getClass()))
235: return false;
236:
237: ManyToOneExpr manyToOne = (ManyToOneExpr) o;
238:
239: return (_parent.equals(manyToOne._parent) && _linkColumns
240: .equals(manyToOne._linkColumns));
241: }
242:
243: public String toString() {
244: return "ManyToOneExpr[" + _childFromItem + "," + _fromItem
245: + "," + _parent + "]";
246: }
247:
248: //
249: // private
250:
251: private void generateInternalWhere(CharBuffer cb, boolean select) {
252: if (_fromItem != null) {
253:
254: if (select) {
255: cb.append(_fromItem.getName());
256: cb.append('.');
257: }
258:
259: cb.append(_linkColumns.getColumns().get(0).getName());
260: } else {
261:
262: if (select)
263: super.generateWhere(cb);
264: else
265: super.generateUpdateWhere(cb);
266: }
267: }
268: }
|