001: /**
002: * Copyright 2006 Webmedia Group Ltd.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: **/package org.araneaframework.backend.list.helper;
016:
017: import java.sql.ResultSet;
018:
019: import javax.sql.DataSource;
020:
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023: import org.araneaframework.backend.list.helper.fields.ConcatFields;
024: import org.araneaframework.backend.list.helper.fields.Fields;
025: import org.araneaframework.backend.list.helper.fields.StandardFields;
026: import org.araneaframework.backend.list.helper.naming.MappingNamingStrategyAndFields;
027: import org.araneaframework.backend.list.helper.naming.NamingStrategy;
028: import org.araneaframework.backend.list.helper.naming.OrNamingStrategy;
029: import org.araneaframework.backend.list.helper.naming.PrefixMapNamingStrategy;
030: import org.araneaframework.backend.list.helper.reader.ConverterBasedColumnReader;
031: import org.araneaframework.backend.list.helper.reader.DefaultResultSetColumnReader;
032: import org.araneaframework.backend.list.helper.reader.ResultSetColumnReader;
033: import org.araneaframework.backend.list.model.ListQuery;
034: import org.araneaframework.uilib.list.util.Converter;
035:
036: /**
037: * This class provides a standard SQL based implementation of the list. It takes care of
038: * the filtering, ordering and returning data to the web components.
039: *
040: * @see BaseListSqlHelper
041: *
042: * @author Jevgeni Kabanov (ekabanov <i>at</i> araneaframework <i>dot</i> org)
043: * @author <a href="mailto:rein@araneaframework.org">Rein Raudjärv</a>
044: */
045: public abstract class ListSqlHelper extends BaseListSqlHelper {
046:
047: protected static final Log log = LogFactory
048: .getLog(ListSqlHelper.class);
049:
050: // *******************************************************************
051: // FIELDS
052: // *******************************************************************
053:
054: protected StandardFields standardFields;
055: protected MappingNamingStrategyAndFields mappingNamingStrategyAndFields;
056: protected PrefixMapNamingStrategy prefixMapNamingStrategy;
057:
058: protected StandardValueConverter standardValueConverter;
059: protected ConverterBasedColumnReader converterBasedColumnReader;
060:
061: // *********************************************************************
062: // * CONSTRUCTORS
063: // *********************************************************************
064:
065: /**
066: * Creates <code>ListSqlHelper</code> without initializing any fields.
067: */
068: public ListSqlHelper() {
069: super ();
070: }
071:
072: /**
073: * Creates <code>ListSqlHelper</code> and provides it with the
074: * <code>DataSource</code>.
075: */
076: public ListSqlHelper(DataSource dataSource) {
077: super (dataSource);
078: }
079:
080: /**
081: * Creates <code>ListSqlHelper</code> initializing the appropriate fields.
082: */
083: public ListSqlHelper(ListQuery query) {
084: super (query);
085: }
086:
087: /**
088: * Creates <code>ListSqlHelper</code> initializing the appropriate fields
089: * and providing it with the <code>DataSource</code>.
090: */
091: public ListSqlHelper(DataSource dataSource, ListQuery query) {
092: super (dataSource, query);
093: }
094:
095: protected void init() {
096: super .init();
097: getPrefixMapNamingStrategy(); // Add naming strategy
098: }
099:
100: // *********************************************************************
101: // * DATABASE MAPPING AND CONVERTERS
102: // *********************************************************************
103:
104: /**
105: * Add additional "set" of fields.
106: *
107: * @see Fields
108: */
109: public void addFields(Fields newFields) {
110: // Update "fields"
111: if (fields == null) {
112: fields = newFields;
113: } else if (fields instanceof ConcatFields) {
114: ((ConcatFields) fields).add(newFields);
115: } else {
116: Fields old = fields;
117: ConcatFields concat = new ConcatFields();
118: concat.add(old);
119: concat.add(newFields);
120: fields = concat;
121: }
122: }
123:
124: /**
125: * Add additional naming strategy.
126: * <p>
127: * The given <code>namingStrategy</code> is added as last in the context of {@link OrNamingStrategy}.
128: *
129: * @see NamingStrategy
130: */
131: public void addNamingStrategy(NamingStrategy namingStrategy) {
132: addNamingStrategy(namingStrategy, false);
133: }
134:
135: /**
136: * Add additional naming strategy.
137: * <p>
138: * The given <code>namingStrategy</code> is added as first in the context of {@link OrNamingStrategy}.
139: *
140: * @see NamingStrategy
141: */
142: public void addNamingStrategyAsFirst(NamingStrategy namingStrategy) {
143: addNamingStrategy(namingStrategy, true);
144: }
145:
146: protected void addNamingStrategy(NamingStrategy newNamingStrategy,
147: boolean first) {
148: // Update "namingStrategy"
149: if (namingStrategy == null) {
150: namingStrategy = newNamingStrategy;
151: } else if (namingStrategy instanceof OrNamingStrategy) {
152: OrNamingStrategy or = (OrNamingStrategy) namingStrategy;
153: if (first) {
154: or.addFirst(newNamingStrategy);
155: } else {
156: or.add(newNamingStrategy);
157: }
158: } else {
159: NamingStrategy old = namingStrategy;
160: OrNamingStrategy or = new OrNamingStrategy();
161: or.add(old);
162: if (first) {
163: or.addFirst(newNamingStrategy);
164: } else {
165: or.add(newNamingStrategy);
166: }
167: namingStrategy = or;
168: }
169: }
170:
171: public void setStandardFields(StandardFields standardFields) {
172: this .standardFields = standardFields;
173: }
174:
175: /**
176: * @return standard implementation of list of fields.
177: */
178: public StandardFields getStandardFields() {
179: if (standardFields == null) {
180: standardFields = new StandardFields();
181: addFields(standardFields);
182: }
183: return standardFields;
184: }
185:
186: public void setMappingNamingStrategyAndFields(
187: MappingNamingStrategyAndFields mappingNamingStrategyAndFields) {
188: this .mappingNamingStrategyAndFields = mappingNamingStrategyAndFields;
189: }
190:
191: public MappingNamingStrategyAndFields getMappingNamingStrategyAndFields() {
192: if (mappingNamingStrategyAndFields == null) {
193: mappingNamingStrategyAndFields = new MappingNamingStrategyAndFields();
194: addFields(mappingNamingStrategyAndFields);
195: addNamingStrategyAsFirst(mappingNamingStrategyAndFields);
196: }
197: return mappingNamingStrategyAndFields;
198: }
199:
200: public void setPrefixMapNamingStrategy(
201: PrefixMapNamingStrategy prefixMapNamingStrategy) {
202: this .prefixMapNamingStrategy = prefixMapNamingStrategy;
203: }
204:
205: public PrefixMapNamingStrategy getPrefixMapNamingStrategy() {
206: if (prefixMapNamingStrategy == null) {
207: prefixMapNamingStrategy = new PrefixMapNamingStrategy();
208: addNamingStrategy(prefixMapNamingStrategy);
209: }
210: return prefixMapNamingStrategy;
211: }
212:
213: public void setStandardValueConverter(
214: StandardValueConverter standardValueConverter) {
215: this .standardValueConverter = standardValueConverter;
216: }
217:
218: public StandardValueConverter getStandardValueConverter() {
219: if (standardValueConverter == null) {
220: standardValueConverter = new StandardValueConverter();
221: valueConverter = standardValueConverter;
222: }
223: return standardValueConverter;
224: }
225:
226: public void setConverterBasedColumnReader(
227: ConverterBasedColumnReader converterBasedColumnReader) {
228: this .converterBasedColumnReader = converterBasedColumnReader;
229: }
230:
231: public ConverterBasedColumnReader getConverterBasedColumnReader() {
232: if (converterBasedColumnReader == null) {
233: ResultSetColumnReader defaultResultSetColumnReader = DefaultResultSetColumnReader
234: .getInstance();
235: converterBasedColumnReader = new ConverterBasedColumnReader(
236: defaultResultSetColumnReader);
237: resultSetColumnReader = converterBasedColumnReader;
238: }
239: return converterBasedColumnReader;
240: }
241:
242: /**
243: * Adds a converter for a filter/order expression value. The converter is
244: * used by auomatic SQL query creation according to the filter/order
245: * expressions.
246: *
247: * @param valueName
248: * filter/order expression value name.
249: * @param converter
250: * converter that is used by <code>convert()</code> method.
251: *
252: * @see #addResultSetDeconverterForBeanField(String, Converter)
253: * @see #addResultSetDeconverterForColumn(String, Converter)
254: */
255: public void addDatabaseFieldConverter(String valueName,
256: Converter converter) {
257: getStandardValueConverter().addConverter(valueName, converter);
258: }
259:
260: /**
261: * Adds a deconverter for <code>ResultSet</code>. The converter is used by
262: * {@link BeanResultReader} to reverseConvert() values from
263: * <code>ResultSet</code> into bean field format.
264: *
265: * @param beanField
266: * Bean field name.
267: * @param converter
268: * converter that is used by <code>reverseConvert()</code>
269: * method.
270: *
271: * @see #addDatabaseFieldConverter(String, Converter)
272: * @see #addResultSetDeconverterForColumn(String, Converter)
273: * @see BeanResultReader
274: */
275: public void addResultSetDeconverterForBeanField(String beanField,
276: Converter converter) {
277: String columnName = namingStrategy
278: .fieldToColumnAlias(beanField);
279: addResultSetDeconverterForColumn(columnName, converter);
280: }
281:
282: /**
283: * Adds a deconverter for <code>ResultSet</code>. The converter is used by
284: * {@link BeanResultReader} to reverseConvert() values from
285: * <code>ResultSet</code> into bean field format.
286: *
287: * @param columnName
288: * ResultSet column name.
289: * @param converter
290: * converter that is used by <code>reverseConvert()</code>
291: * method.
292: *
293: * @see #addDatabaseFieldConverter(String, Converter)
294: * @see #addResultSetDeconverterForBeanField(String, Converter)
295: * @see BeanResultReader
296: */
297: public void addResultSetDeconverterForColumn(String columnName,
298: Converter converter) {
299: getConverterBasedColumnReader()
300: .addResultSetDeconverterForColumn(columnName, converter);
301: }
302:
303: // Mappings
304:
305: /**
306: * Adds a <b>field name</b> to database <b>column name</b> and <b>column alias</b> mapping.
307: * <p>
308: * A given field is listed in the <code>SELECT</code> but is not read from the {@link ResultSet}.
309: *
310: * @param fieldName
311: * field name.
312: * @param columnName
313: * database column name.
314: * @param columnAlias
315: * database column alias.
316: *
317: * @see #addMapping(String, String, String)
318: * @see #addMapping(String, String)
319: * @see #addDatabaseFieldMapping(String, String)
320: * @see #addResultSetMapping(String, String)
321: */
322: public void addDatabaseFieldMapping(String fieldName,
323: String columnName, String columnAlias) {
324: getMappingNamingStrategyAndFields().addDatabaseFieldMapping(
325: fieldName, columnName, columnAlias);
326: }
327:
328: /**
329: * Adds a <b>field name</b> to database <b>column name</b> mapping.
330: * <p>
331: * A given field is listed in the <code>SELECT</code> but is not read from the {@link ResultSet}.
332: * </p>
333: * <p>
334: * The corresponding <b>column alias</b> is generated automatically.
335: *
336: * @param fieldName
337: * field name.
338: * @param columnName
339: * database column name.
340: *
341: * @see #addMapping(String, String, String)
342: * @see #addMapping(String, String)
343: * @see #addDatabaseFieldMapping(String, String, String)
344: * @see #addResultSetMapping(String, String)
345: */
346: public void addDatabaseFieldMapping(String fieldName,
347: String columnName) {
348: getMappingNamingStrategyAndFields().addDatabaseFieldMapping(
349: fieldName, columnName);
350: }
351:
352: /**
353: * Adds a <b>field name</b> to database <b>column alias</b> mapping.
354: * <p>
355: * A given field is not listed in the <code>SELECT</code> but is read from the {@link ResultSet}.
356: * </p>
357: *
358: * @param fieldName
359: * field name.
360: * @param columnAlias
361: * database column name in the result set.
362: *
363: * @see #addMapping(String, String, String)
364: * @see #addMapping(String, String)
365: * @see #addDatabaseFieldMapping(String, String, String)
366: * @see #addDatabaseFieldMapping(String, String)
367: */
368: public void addResultSetMapping(String fieldName, String columnAlias) {
369: getMappingNamingStrategyAndFields().addResultSetMapping(
370: fieldName, columnAlias);
371: }
372:
373: /**
374: * Adds a <b>field name</b> to database <b>column name</b> and <b>column alias</b> mapping.
375: * <p>
376: * A given field is listed in the <code>SELECT</code> and is read from the {@link ResultSet}.
377: *
378: * @param fieldName
379: * field name.
380: * @param columnName
381: * database column name.
382: * @param columnAlias
383: * database column alias.
384: *
385: * @see #addMapping(String, String)
386: * @see #addDatabaseFieldMapping(String, String, String)
387: * @see #addDatabaseFieldMapping(String, String)
388: * @see #addResultSetMapping(String, String)
389: */
390: public void addMapping(String fieldName, String columnName,
391: String columnAlias) {
392: getMappingNamingStrategyAndFields().addMapping(fieldName,
393: columnName, columnAlias);
394: }
395:
396: /**
397: * Adds a <b>field name</b> to database <b>column name</b>.
398: * <p>
399: * A given field is listed in the <code>SELECT</code> and is read from the {@link ResultSet}.
400: * </p>
401: * <p>
402: * The corresponding <b>column alias</b> is generated automatically.
403: *
404: * @param fieldName
405: * field name.
406: * @param columnName
407: * database column name.
408: *
409: * @see #addMapping(String, String, String)
410: * @see #addDatabaseFieldMapping(String, String, String)
411: * @see #addDatabaseFieldMapping(String, String)
412: * @see #addResultSetMapping(String, String)
413: */
414: public void addMapping(String fieldName, String columnName) {
415: getMappingNamingStrategyAndFields().addMapping(fieldName,
416: columnName);
417: }
418:
419: }
|