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.meta.strats;
020:
021: import java.sql.SQLException;
022: import java.util.Collection;
023: import java.util.Map;
024:
025: import org.apache.openjpa.conf.OpenJPAConfiguration;
026: import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
027: import org.apache.openjpa.jdbc.kernel.JDBCStore;
028: import org.apache.openjpa.jdbc.meta.ClassMapping;
029: import org.apache.openjpa.jdbc.meta.FieldMapping;
030: import org.apache.openjpa.jdbc.meta.ValueMapping;
031: import org.apache.openjpa.jdbc.schema.Column;
032: import org.apache.openjpa.jdbc.schema.ForeignKey;
033: import org.apache.openjpa.jdbc.sql.Joins;
034: import org.apache.openjpa.jdbc.sql.Result;
035: import org.apache.openjpa.jdbc.sql.Select;
036: import org.apache.openjpa.jdbc.sql.Union;
037: import org.apache.openjpa.kernel.OpenJPAStateManager;
038: import org.apache.openjpa.lib.util.Localizer;
039: import org.apache.openjpa.meta.JavaTypes;
040: import org.apache.openjpa.util.InternalException;
041: import org.apache.openjpa.util.MetaDataException;
042: import org.apache.openjpa.util.Proxy;
043:
044: /**
045: * Uses an association table to hold map values. Derives map keys from
046: * a field in each value.
047: *
048: * @author Abe White
049: */
050: public class RelationMapTableFieldStrategy extends
051: RelationToManyTableFieldStrategy implements LRSMapFieldStrategy {
052:
053: private static final Localizer _loc = Localizer
054: .forPackage(RelationMapTableFieldStrategy.class);
055:
056: public FieldMapping getFieldMapping() {
057: return field;
058: }
059:
060: public ClassMapping[] getIndependentKeyMappings(boolean traverse) {
061: return ClassMapping.EMPTY_MAPPINGS;
062: }
063:
064: public ClassMapping[] getIndependentValueMappings(boolean traverse) {
065: return getIndependentElementMappings(traverse);
066: }
067:
068: public ForeignKey getJoinForeignKey(ClassMapping cls) {
069: return super .getJoinForeignKey(cls);
070: }
071:
072: public Column[] getKeyColumns(ClassMapping cls) {
073: return cls.getFieldMapping(
074: field.getKey().getValueMappedByMetaData().getIndex())
075: .getColumns();
076: }
077:
078: public Column[] getValueColumns(ClassMapping cls) {
079: return field.getElementMapping().getColumns();
080: }
081:
082: public void selectKey(Select sel, ClassMapping key,
083: OpenJPAStateManager sm, JDBCStore store,
084: JDBCFetchConfiguration fetch, Joins joins) {
085: throw new InternalException();
086: }
087:
088: public Object loadKey(OpenJPAStateManager sm, JDBCStore store,
089: JDBCFetchConfiguration fetch, Result res, Joins joins)
090: throws SQLException {
091: throw new InternalException();
092: }
093:
094: public Object deriveKey(JDBCStore store, Object value) {
095: OpenJPAStateManager sm = RelationStrategies.getStateManager(
096: value, store.getContext());
097: return (sm == null) ? null : sm.fetchField(field.getKey()
098: .getValueMappedByMetaData().getIndex(), false);
099: }
100:
101: public Object deriveValue(JDBCStore store, Object key) {
102: return null;
103: }
104:
105: public void selectValue(Select sel, ClassMapping val,
106: OpenJPAStateManager sm, JDBCStore store,
107: JDBCFetchConfiguration fetch, Joins joins) {
108: selectElement(sel, val, store, fetch,
109: JDBCFetchConfiguration.EAGER_NONE, joins);
110: }
111:
112: public Object loadValue(OpenJPAStateManager sm, JDBCStore store,
113: JDBCFetchConfiguration fetch, Result res, Joins joins)
114: throws SQLException {
115: return loadElement(sm, store, fetch, res, joins);
116: }
117:
118: public Result[] getResults(final OpenJPAStateManager sm,
119: final JDBCStore store, final JDBCFetchConfiguration fetch,
120: final int eagerMode, final Joins[] joins, boolean lrs)
121: throws SQLException {
122: ValueMapping val = field.getElementMapping();
123: final ClassMapping[] vals = val.getIndependentTypeMappings();
124: Union union = store.getSQLFactory().newUnion(vals.length);
125: if (fetch.getSubclassFetchMode(val.getTypeMapping()) != JDBCFetchConfiguration.EAGER_JOIN)
126: union.abortUnion();
127: union.setLRS(lrs);
128: union.select(new Union.Selector() {
129: public void select(Select sel, int idx) {
130: joins[1] = selectAll(sel, vals[idx], sm, store, fetch,
131: eagerMode);
132: }
133: });
134: Result res = union.execute(store, fetch);
135: return new Result[] { res, res };
136: }
137:
138: public Joins joinKeyRelation(Joins joins, ClassMapping key) {
139: return joins;
140: }
141:
142: public Joins joinValueRelation(Joins joins, ClassMapping val) {
143: return joinElementRelation(joins, val);
144: }
145:
146: protected Proxy newLRSProxy() {
147: return new LRSProxyMap(this );
148: }
149:
150: protected void add(JDBCStore store, Object coll, Object obj) {
151: if (obj != null)
152: ((Map) coll).put(deriveKey(store, obj), obj);
153: }
154:
155: protected Collection toCollection(Object val) {
156: return (val == null) ? null : ((Map) val).values();
157: }
158:
159: public void map(boolean adapt) {
160: if (field.getTypeCode() != JavaTypes.MAP)
161: throw new MetaDataException(_loc.get("not-map", field));
162: if (field.getKey().getValueMappedBy() == null)
163: throw new MetaDataException(_loc.get("not-mapped-by-key",
164: field));
165: super .map(adapt);
166: }
167:
168: public Joins joinKey(Joins joins, boolean forceOuter) {
169: return joinRelation(join(joins, forceOuter), forceOuter, false);
170: }
171: }
|