001: package net.sourceforge.orbroker;
002:
003: import java.lang.reflect.Array;
004: import java.sql.Connection;
005: import java.util.ArrayList;
006: import java.util.Collection;
007: import java.util.HashMap;
008: import java.util.HashSet;
009: import java.util.Iterator;
010: import java.util.List;
011: import java.util.Map;
012: import java.util.Set;
013: import java.util.SortedSet;
014: import java.util.TreeSet;
015:
016: /*
017: * Created on Mar 24, 2004
018: *
019: */
020:
021: /**
022: * @author Nils Kilden-Pedersen
023: */
024: final class SubQuery extends ValueType {
025:
026: private String statementID;
027: private Broker broker;
028: private Map valueTypes = new HashMap();
029: private boolean isLazyCollection;
030:
031: SubQuery(Class type, String statementID, Broker broker, boolean lazy) {
032: super (type);
033: this .statementID = statementID;
034: this .broker = broker;
035: this .isLazyCollection = lazy;
036: }
037:
038: void addParameterValue(String name, Object value) {
039: this .valueTypes.put(name, value);
040: }
041:
042: /**
043: * @see net.sourceforge.orbroker.ValueType#getValue(net.sourceforge.orbroker.ResultRow)
044: */
045: Object getValue(ResultRow row) {
046: ConnectionContext context = new ConnectionContext();
047: context.setTextReplacements(row.getTextReplacements());
048: context.setParameters(getParameterValues(row));
049:
050: if (!this .isLazyCollection) {
051: return getImmediateValue(context, row.getConnection());
052: }
053:
054: Class this Type = getType();
055: if (SortedSet.class.equals(this Type)) {
056: return new LazySortedSet(this .broker, this .statementID,
057: context);
058: } else if (Set.class.equals(this Type)) {
059: return new LazySet(this .broker, this .statementID, context);
060: } else if (List.class.equals(this Type)
061: || Collection.class.equals(this Type)) {
062: return new LazyList(this .broker, this .statementID, context);
063: }
064: String msg = "Lazy collections only works on Collection interfaces";
065: throw new ConfigurationException(msg);
066: }
067:
068: private Parameters getParameterValues(ResultRow row) {
069: Parameters values = new Parameters();
070: Iterator varEntries = this .valueTypes.entrySet().iterator();
071: while (varEntries.hasNext()) {
072: Map.Entry entry = (Map.Entry) varEntries.next();
073: String varName = (String) entry.getKey();
074: ValueType varType = (ValueType) entry.getValue();
075: Object value = varType.getValue(row);
076: values.addParameter(varName, value);
077: }
078: return values;
079: }
080:
081: private Object getImmediateValue(ConnectionContext context,
082: Connection con) {
083:
084: Object result;
085: Executable exe = this .broker.obtainExecutable(con);
086: exe.addContext(context);
087: Class requiredType = getType();
088: Class nonPrimitiveArrayType = null;
089: if (requiredType.isArray()) {
090: nonPrimitiveArrayType = requiredType.getComponentType();
091: if (nonPrimitiveArrayType.isPrimitive()) {
092: nonPrimitiveArrayType = null;
093: }
094: }
095: try {
096: if (Collection.class.isAssignableFrom(requiredType)) {
097: result = createCollectionInstance();
098: exe.selectMany(this .statementID, (Collection) result);
099: } else if (nonPrimitiveArrayType != null) {
100: List list = exe.selectMany(this .statementID);
101: result = Array.newInstance(nonPrimitiveArrayType, list
102: .size());
103: list.toArray((Object[]) result);
104: } else {
105: result = exe.selectOne(this .statementID);
106: }
107: } finally {
108: /* Do not use Broker.releaseExecutable
109: since it clears cache for connection. */
110: exe.release();
111: }
112: return result;
113: }
114:
115: private Collection createCollectionInstance() {
116:
117: if (getType().isInterface()) {
118: if (Collection.class.equals(getType())
119: || List.class.isAssignableFrom(getType())) {
120: return new ArrayList();
121: } else if (Set.class.isAssignableFrom(getType())) {
122: return new HashSet();
123: } else if (SortedSet.class.isAssignableFrom(getType())) {
124: return new TreeSet();
125: }
126: }
127:
128: try {
129: return (Collection) getType().newInstance();
130: } catch (InstantiationException e) {
131: // Throw exception below
132: } catch (ClassCastException e) {
133: assert false : "Method should only be called after checking type is Collection.";
134: } catch (Exception e) {
135: throw new ReflectionException(e);
136: }
137: String msg = "Cannot create " + getType();
138: throw new ConfigurationException(msg);
139: }
140:
141: }
|