001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.jdbc.kernel.exps;
020:
021: import java.sql.SQLException;
022:
023: import org.apache.openjpa.jdbc.meta.ClassMapping;
024: import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
025: import org.apache.openjpa.jdbc.sql.Result;
026: import org.apache.openjpa.jdbc.sql.SQLBuffer;
027: import org.apache.openjpa.jdbc.sql.Select;
028: import org.apache.openjpa.kernel.Filters;
029: import org.apache.openjpa.kernel.exps.ExpressionVisitor;
030: import org.apache.openjpa.meta.ClassMetaData;
031:
032: /**
033: * Aggregate listener that evaluates to a value.
034: *
035: * @author Abe White
036: */
037: class Aggregate extends AbstractVal {
038:
039: private final JDBCAggregateListener _listener;
040: private final Val _arg;
041: private final ClassMapping _candidate;
042: private ClassMetaData _meta = null;
043: private Class _cast = null;
044:
045: /**
046: * Constructor.
047: */
048: public Aggregate(JDBCAggregateListener listener, Val arg,
049: ClassMapping candidate) {
050: _listener = listener;
051: _arg = arg;
052: _candidate = candidate;
053: }
054:
055: public ClassMetaData getMetaData() {
056: return _meta;
057: }
058:
059: public void setMetaData(ClassMetaData meta) {
060: _meta = meta;
061: }
062:
063: public boolean isAggregate() {
064: return true;
065: }
066:
067: public Class getType() {
068: if (_cast != null)
069: return _cast;
070: return _listener.getType(getArgTypes());
071: }
072:
073: private Class[] getArgTypes() {
074: if (_arg == null)
075: return null;
076: if (_arg instanceof Args)
077: return ((Args) _arg).getTypes();
078: return new Class[] { _arg.getType() };
079: }
080:
081: public void setImplicitType(Class type) {
082: _cast = type;
083: }
084:
085: public ExpState initialize(Select sel, ExpContext ctx, int flags) {
086: if (_arg == null)
087: return ExpState.NULL;
088:
089: // note that we tell targets and args to extensions that are sql
090: // paths to go ahead and join to their related object (if any),
091: // because we assume that, unlike most operations, if a relation
092: // field like a 1-1 is given as the target of an extension, then
093: // the extension probably acts on some field or column in the
094: // related object, not the 1-1 field itself
095: return _arg.initialize(sel, ctx, JOIN_REL);
096: }
097:
098: public void select(Select sel, ExpContext ctx, ExpState state,
099: boolean pks) {
100: sel.select(newSQLBuffer(sel, ctx, state), this );
101: sel.setAggregate(true);
102: }
103:
104: public void selectColumns(Select sel, ExpContext ctx,
105: ExpState state, boolean pks) {
106: if (_arg != null)
107: _arg.selectColumns(sel, ctx, state, true);
108: }
109:
110: public void groupBy(Select sel, ExpContext ctx, ExpState state) {
111: sel.groupBy(newSQLBuffer(sel, ctx, state));
112: }
113:
114: public void orderBy(Select sel, ExpContext ctx, ExpState state,
115: boolean asc) {
116: sel.orderBy(newSQLBuffer(sel, ctx, state), asc, false);
117: }
118:
119: private SQLBuffer newSQLBuffer(Select sel, ExpContext ctx,
120: ExpState state) {
121: calculateValue(sel, ctx, state, null, null);
122: SQLBuffer buf = new SQLBuffer(ctx.store.getDBDictionary());
123: appendTo(sel, ctx, state, buf, 0);
124: return buf;
125: }
126:
127: public Object load(ExpContext ctx, ExpState state, Result res)
128: throws SQLException {
129: return Filters.convert(res.getObject(this ,
130: JavaSQLTypes.JDBC_DEFAULT, null), getType());
131: }
132:
133: public void calculateValue(Select sel, ExpContext ctx,
134: ExpState state, Val other, ExpState otherState) {
135: if (_arg != null)
136: _arg.calculateValue(sel, ctx, state, null, null);
137: }
138:
139: public int length(Select sel, ExpContext ctx, ExpState state) {
140: return 1;
141: }
142:
143: public void appendTo(Select sel, ExpContext ctx, ExpState state,
144: SQLBuffer sql, int index) {
145: _listener.appendTo(sql, getArgs(sel, ctx, state), _candidate,
146: ctx.store);
147: sel.append(sql, state.joins);
148: }
149:
150: private FilterValue[] getArgs(Select sel, ExpContext ctx,
151: ExpState state) {
152: if (_arg == null)
153: return null;
154: if (_arg instanceof Args)
155: return ((Args) _arg).newFilterValues(sel, ctx, state);
156: return new FilterValue[] { new FilterValueImpl(sel, ctx, state,
157: _arg) };
158: }
159:
160: public void acceptVisit(ExpressionVisitor visitor) {
161: visitor.enter(this);
162: if (_arg != null)
163: _arg.acceptVisit(visitor);
164: visitor.exit(this);
165: }
166: }
|