001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.jdbc.fetch;
012:
013: import com.versant.core.common.BindingSupportImpl;
014: import com.versant.core.jdbc.sql.exp.SelectExp;
015: import com.versant.core.jdbc.sql.exp.SqlExp;
016:
017: import java.sql.SQLException;
018: import java.io.PrintStream;
019:
020: /**
021: * On object or field fetch in an EJBQL query. An array of these is contructed
022: * for the select list of an EJBQL query and any eager fetched fields (i.e.
023: * fields in the default fetch group).
024: */
025: public abstract class FetchOp {
026:
027: protected final FetchSpec spec;
028: private int index;
029:
030: public FetchOp(FetchSpec spec) {
031: this .spec = spec;
032: }
033:
034: /**
035: * Init this FetchOp and return the expressions that we need to be added
036: * to the select list of the query or null if none. The FetchOp may
037: * add additional FetchOp's to the spec.
038: */
039: public abstract SqlExp init(SelectExp root, int firstColIndex);
040:
041: /**
042: * Return a FetchOpData that accesses the output we produce. This can be
043: * used when creating other FetchOp's that need this output.
044: */
045: public abstract FetchOpData getOutputData();
046:
047: /**
048: * Fetch our data.
049: */
050: public abstract void fetch(FetchResultImp fetchResult)
051: throws SQLException;
052:
053: /**
054: * Get a one line user understandable description of this operation.
055: */
056: public abstract String getDescription();
057:
058: /**
059: * Print a user understandable description of this operation.
060: */
061: public void printPlan(PrintStream p, String indent) {
062: p.println(indent + getIndex() + ": " + getName() + " "
063: + getDescription());
064: }
065:
066: /**
067: * Get the name of this op. The default is the unqualified class name with
068: * any Fop prefix removed.
069: */
070: public String getName() {
071: String cname = getClass().getName();
072: int i = cname.lastIndexOf(".Fop");
073: if (i < 0) {
074: i = cname.lastIndexOf('.') + 1;
075: } else {
076: i += 4;
077: }
078: return cname.substring(i);
079: }
080:
081: /**
082: * This is called after our spec has generated its SQL. Generate SQL for
083: * any nested FetchSpec's and clear fields no longer needed (e.g. any
084: * SqlExp type fields).
085: */
086: public void generateSQL() {
087: }
088:
089: /**
090: * This is invoked when a FetchResult from our FetchSpec is closed.
091: * Closed any nested queries etc.
092: */
093: public void fetchResultClosed(FetchResult fetchResult) {
094: }
095:
096: /**
097: * Get an object to be included in fetch projection.
098: */
099: public Object getResult(FetchResultImp fetchResult) {
100: throw notImplemented();
101: }
102:
103: /**
104: * Get the type of our result (INTW, OID, STRING etc).
105: *
106: * @see com.versant.core.metadata.MDStatics.OID
107: */
108: public int getResultType() {
109: throw notImplemented();
110: }
111:
112: public FetchSpec getSpec() {
113: return spec;
114: }
115:
116: public int getIndex() {
117: return index;
118: }
119:
120: public void setIndex(int index) {
121: this .index = index;
122: }
123:
124: public RuntimeException notImplemented() {
125: return notImplemented("Not implemented for " + toString());
126: }
127:
128: public RuntimeException notImplemented(String msg) {
129: return internal(msg);
130: }
131:
132: public RuntimeException internal(String msg) {
133: return BindingSupportImpl.getInstance().internal(msg);
134: }
135:
136: public String toString() {
137: String s;
138: try {
139: s = toStringImp();
140: } catch (Exception e) {
141: s = "<toStringImp failed: " + e + ">";
142: }
143: return index + ": " + getName() + " " + getDescription()
144: + (s == null ? "" : " " + s);
145: }
146:
147: /**
148: * Override this to provide subclass specific info for toString that is
149: * not already provided by getDescription.
150: */
151: protected String toStringImp() {
152: return null;
153: }
154:
155: }
|