1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.openjpa.jdbc.meta.strats;
20
21 import java.sql.SQLException;
22
23 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
24 import org.apache.openjpa.jdbc.kernel.JDBCStore;
25 import org.apache.openjpa.jdbc.meta.Embeddable;
26 import org.apache.openjpa.jdbc.meta.FieldMapping;
27 import org.apache.openjpa.jdbc.meta.Joinable;
28 import org.apache.openjpa.jdbc.meta.ValueMappingInfo;
29 import org.apache.openjpa.jdbc.schema.Column;
30 import org.apache.openjpa.jdbc.schema.ColumnIO;
31 import org.apache.openjpa.jdbc.schema.ForeignKey;
32 import org.apache.openjpa.jdbc.schema.PrimaryKey;
33 import org.apache.openjpa.jdbc.sql.Joins;
34 import org.apache.openjpa.jdbc.sql.Result;
35 import org.apache.openjpa.jdbc.sql.Row;
36 import org.apache.openjpa.jdbc.sql.RowManager;
37 import org.apache.openjpa.jdbc.sql.SQLBuffer;
38 import org.apache.openjpa.jdbc.sql.Select;
39 import org.apache.openjpa.kernel.OpenJPAStateManager;
40 import org.apache.openjpa.lib.util.Localizer;
41 import org.apache.openjpa.meta.JavaTypes;
42 import org.apache.openjpa.meta.ValueStrategies;
43 import org.apache.openjpa.util.MetaDataException;
44
45 /**
46 * Direct mapping from a string value to a column.
47 *
48 * @author Abe White
49 * @since 0.4.0
50 */
51 public class StringFieldStrategy
52 extends AbstractFieldStrategy
53 implements Joinable, Embeddable {
54
55 private static final Localizer _loc = Localizer.forPackage
56 (StringFieldStrategy.class);
57
58 public void map(boolean adapt) {
59 if (field.getTypeCode() != JavaTypes.STRING)
60 throw new MetaDataException(_loc.get("not-string", field));
61 assertNotMappedBy();
62
63 // map join key, if any
64 field.mapJoin(adapt, false);
65 field.getKeyMapping().getValueInfo().assertNoSchemaComponents
66 (field.getKey(), !adapt);
67 field.getElementMapping().getValueInfo().assertNoSchemaComponents
68 (field.getElement(), !adapt);
69
70 ValueMappingInfo vinfo = field.getValueInfo();
71 vinfo.assertNoJoin(field, true);
72 vinfo.assertNoForeignKey(field, !adapt);
73
74 // get value columns
75 Column tmpCol = new Column();
76 tmpCol.setName(field.getName());
77 tmpCol.setJavaType(field.getTypeCode());
78
79 Column[] cols = vinfo.getColumns(field, field.getName(),
80 new Column[]{ tmpCol }, field.getTable(), adapt);
81 if (field.getValueStrategy() == ValueStrategies.AUTOASSIGN)
82 cols[0].setAutoAssigned(true);
83
84 field.setColumns(cols);
85 field.setColumnIO(vinfo.getColumnIO());
86 field.mapConstraints(field.getName(), adapt);
87
88 // add primary key columns to table pk if logical
89 field.mapPrimaryKey(adapt);
90 PrimaryKey pk = field.getTable().getPrimaryKey();
91 if (field.isPrimaryKey() && pk != null && (adapt || pk.isLogical()))
92 pk.addColumn(cols[0]);
93
94 // set joinable
95 field.getDefiningMapping().setJoinable(field.getColumns()[0], this);
96 }
97
98 public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
99 throws SQLException {
100 String str = (String) toDataStoreValue(sm.fetchString
101 (field.getIndex()), store);
102 if (field.getColumnIO().isInsertable(0, str == null)) {
103 Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT);
104 if (row != null)
105 row.setString(field.getColumns()[0], str);
106 }
107 }
108
109 public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
110 throws SQLException {
111 String str = (String) toDataStoreValue(sm.fetchString
112 (field.getIndex()), store);
113 if (field.getColumnIO().isUpdatable(0, str == null)) {
114 Row row = field.getRow(sm, store, rm, Row.ACTION_UPDATE);
115 if (row != null)
116 row.setString(field.getColumns()[0], str);
117 }
118 }
119
120 public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
121 throws SQLException {
122 field.deleteRow(sm, store, rm);
123 }
124
125 public Object toDataStoreValue(Object val, JDBCStore store) {
126 if (val != null)
127 return val;
128
129 if (field.getNullValue() != FieldMapping.NULL_DEFAULT)
130 return null;
131 if (field.getColumns()[0].getDefaultString() != null)
132 return null;
133 // honor the user's null-value=default
134 return "";
135 }
136
137 public int supportsSelect(Select sel, int type, OpenJPAStateManager sm,
138 JDBCStore store, JDBCFetchConfiguration fetch) {
139 if (type == Select.TYPE_JOINLESS && sel.isSelected(field.getTable()))
140 return 1;
141 return 0;
142 }
143
144 public int select(Select sel, OpenJPAStateManager sm, JDBCStore store,
145 JDBCFetchConfiguration fetch, int eagerMode) {
146 sel.select(field.getColumns()[0], field.join(sel));
147 return 1;
148 }
149
150 public void load(OpenJPAStateManager sm, JDBCStore store,
151 JDBCFetchConfiguration fetch, Result res)
152 throws SQLException {
153 Column col = field.getColumns()[0];
154 if (res.contains(col))
155 sm.storeString(field.getIndex(), res.getString(col));
156 }
157
158 public void appendIsNull(SQLBuffer sql, Select sel, Joins joins) {
159 joins = join(joins, false);
160 sql.append(sel.getColumnAlias(field.getColumns()[0], joins)).
161 append(" IS ").appendValue(null, field.getColumns()[0]);
162 }
163
164 public void appendIsNotNull(SQLBuffer sql, Select sel, Joins joins) {
165 joins = join(joins, false);
166 sql.append(sel.getColumnAlias(field.getColumns()[0], joins)).
167 append(" IS NOT ").appendValue(null, field.getColumns()[0]);
168 }
169
170 public Joins join(Joins joins, boolean forceOuter) {
171 return field.join(joins, forceOuter, false);
172 }
173
174 public Object loadProjection(JDBCStore store, JDBCFetchConfiguration fetch,
175 Result res, Joins joins)
176 throws SQLException {
177 return res.getString(field.getColumns()[0], joins);
178 }
179
180 public boolean isVersionable() {
181 return true;
182 }
183
184 public void where(OpenJPAStateManager sm, JDBCStore store, RowManager rm,
185 Object prevValue)
186 throws SQLException {
187 Row row = field.getRow(sm, store, rm, Row.ACTION_UPDATE);
188 if (row == null)
189 return;
190
191 Column col = field.getColumns()[0];
192 if (prevValue == null)
193 row.whereNull(col);
194 else
195 row.whereString(col, prevValue.toString());
196 }
197
198 ///////////////////////////
199 // Joinable implementation
200 ///////////////////////////
201
202 public int getFieldIndex() {
203 return field.getIndex();
204 }
205
206 public Object getPrimaryKeyValue(Result res, Column[] cols, ForeignKey fk,
207 JDBCStore store, Joins joins)
208 throws SQLException {
209 Column col = cols[0];
210 if (fk != null)
211 col = fk.getColumn(col);
212 return res.getString(col, joins);
213 }
214
215 public Column[] getColumns() {
216 return field.getColumns();
217 }
218
219 public Object getJoinValue(Object fieldVal, Column col, JDBCStore store) {
220 return fieldVal;
221 }
222
223 public Object getJoinValue(OpenJPAStateManager sm, Column col,
224 JDBCStore store) {
225 return sm.fetch(field.getIndex());
226 }
227
228 public void setAutoAssignedValue(OpenJPAStateManager sm, JDBCStore store,
229 Column col, Object autoInc) {
230 String str = (autoInc == null) ? null : autoInc.toString();
231 sm.storeString(field.getIndex(), str);
232 }
233
234 /////////////////////////////
235 // Embeddable implementation
236 /////////////////////////////
237
238 public ColumnIO getColumnIO() {
239 return field.getColumnIO();
240 }
241
242 public Object[] getResultArguments() {
243 return null;
244 }
245
246 public Object toEmbeddedDataStoreValue(Object val, JDBCStore store) {
247 return toDataStoreValue(val, store);
248 }
249
250 public Object toEmbeddedObjectValue(Object val) {
251 return val;
252 }
253
254 public void loadEmbedded(OpenJPAStateManager sm, JDBCStore store,
255 JDBCFetchConfiguration fetch, Object val)
256 throws SQLException {
257 sm.storeString(field.getIndex(), (String) val);
258 }
259 }