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.metadata.FetchGroup;
014: import com.versant.core.metadata.ClassMetaData;
015: import com.versant.core.jdbc.sql.exp.SelectExp;
016: import com.versant.core.jdbc.sql.exp.SqlExp;
017: import com.versant.core.common.State;
018: import com.versant.core.common.OID;
019:
020: import java.sql.SQLException;
021:
022: /**
023: * A fetch of a complete State (Entity) for an existing OID.
024: */
025: public class FopGetState extends FetchOp {
026:
027: private final FetchOpData src;
028: private final FetchGroup fg;
029: private final boolean includeSubClasses;
030: private final Data data;
031:
032: private int firstColIndex; // the index of our first select list col
033:
034: /**
035: * This gets our state from fetchData and delegates to our src for
036: * the OID and ResultSet.
037: */
038: public class Data extends FetchOpDataProxy {
039:
040: public Data(FetchOpData src) {
041: super (src);
042: }
043:
044: public void setState(FetchResultImp fetchResult, State state) {
045: fetchResult.setData(FopGetState.this , state);
046: }
047:
048: public State getState(FetchResultImp fetchResult) {
049: return (State) fetchResult.getData(FopGetState.this );
050: }
051:
052: public String getDescription() {
053: return " [" + getIndex() + "]";
054: }
055: }
056:
057: /**
058: * Create a State and populate it according to fg. If includeSubclasses is
059: * true then fields for all possible subclasses are fetched. The src must
060: * provide the OID of the instance being fetched and the ResultSet.
061: */
062: public FopGetState(FetchSpec spec, FetchOpData src, FetchGroup fg,
063: boolean includeSubClasses) {
064: super (spec);
065: this .src = src;
066: this .fg = fg;
067: this .includeSubClasses = includeSubClasses
068: && fg.classMetaData.pcSubclasses != null;
069: data = new Data(src);
070: }
071:
072: public FetchOpData getOutputData() {
073: return data;
074: }
075:
076: /**
077: * Add in whatever columns we need to have in the select list and return
078: * the last SqlExp we added.
079: *
080: * - may add new FetchOp's for superclass fields, subclass fields,
081: * prefetched references, collection fields and so on to the plan
082: */
083: public SqlExp init(SelectExp root, int firstColIndex) {
084: this .firstColIndex = firstColIndex;
085: ClassMetaData cmd = fg.classMetaData;
086: if (cmd.isInHeirachy()) {
087: // todo put in columns or create op to figure out the actual class
088: throw notImplemented();
089: }
090: // create ops to fetch all super fetch groups
091: for (FetchGroup g = fg; g != null; g = g.super FetchGroup) {
092: processFetchGroup(g);
093: }
094: // and recusively groups for all possible subclasses (if needed)
095: if (includeSubClasses) {
096: processSubFetchGroups(fg.subFetchGroups);
097: }
098: return null;
099: }
100:
101: private void processFetchGroup(FetchGroup g) {
102: spec.addFetchOp(new FopGetFetchGroup(spec, data, g), false);
103: }
104:
105: private void processSubFetchGroups(FetchGroup[] subs) {
106: if (subs != null) {
107: int n = subs.length;
108: for (int i = 0; i < n; i++) {
109: processFetchGroup(subs[i]);
110: }
111: for (int i = 0; i < n; i++) {
112: processSubFetchGroups(subs[i].subFetchGroups);
113: }
114: }
115: }
116:
117: public void fetch(FetchResultImp fetchResult) throws SQLException {
118: OID oid = src.getOID(fetchResult);
119: if (oid == null) {
120: return; // nothing to fetch
121: }
122: ClassMetaData cmd = fg.classMetaData;
123: if (cmd.isInHeirachy()) {
124: // todo figure out correct cmd
125: throw notImplemented();
126: }
127: State state = cmd.createState();
128: oid.resolve(state);
129: data.setState(fetchResult, state);
130: }
131:
132: public String getDescription() {
133: return fg.classMetaData.qname
134: + (includeSubClasses ? " and subclasses" : "")
135: + src.getDescription();
136: }
137:
138: public int getResultType() {
139: return 0;
140: }
141:
142: public Object getResult(FetchResultImp fetchResult) {
143: return data.getState(fetchResult);
144: }
145:
146: }
|