001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: package org.jaffa.components.finder;
051:
052: import org.apache.log4j.Logger;
053: import java.util.*;
054: import org.jaffa.presentation.portlet.component.Component;
055: import org.jaffa.components.dto.HeaderDto;
056: import org.jaffa.presentation.portlet.widgets.controller.DropDownController;
057: import org.jaffa.presentation.portlet.widgets.model.DropDownModel;
058: import org.jaffa.presentation.portlet.FormKey;
059: import org.jaffa.exceptions.ApplicationExceptions;
060: import org.jaffa.exceptions.FrameworkException;
061: import org.jaffa.security.VariationContext;
062:
063: /** This is the base class for all Finder components created by using the object_finder_2_0 pattern.
064: * It has the following properties -
065: * 1- displayResultsScreen : If set to true, then the Results screen will be directly brought up, bypassing the Criteria screen.
066: * 2- consolidatedCriteriaAndResults : If set to true, then the Criteria and Results screen will be shown together
067: * 3- sortDropDown : The sort criteria to use for the inquiry
068: * 4- exportType : The export option to use for the inquiry (initialized to regular Web Pages)
069: * 5- maxRecords: The maximum number of records to retrieve. All records will be retrieved, if no value is specified.
070: *
071: * A Finder class will have to provide an implementation for the doInquiry(), getCriteriaFormName(), getResultsFormName() and getConsolidatedCriteriaAndResultsFormName() methods.
072: * @author GautamJ
073: */
074: public abstract class FinderComponent2 extends Component {
075:
076: private static final Logger log = Logger
077: .getLogger(FinderComponent2.class);
078: private static final String SPACE = " ";
079: private static final String COMMA = ",";
080: private static final String DESC = "DESC";
081:
082: /** A global constant for the Web Page export option.*/
083: public final static String EXPORT_TYPE_WEB_PAGE = "W";
084: /** A global constant for the Excel export option.*/
085: public final static String EXPORT_TYPE_EXCEL = "E";
086: /** A global constant for the XML export option.*/
087: public final static String EXPORT_TYPE_XML = "X";
088: /** This request stream attribute is set after a query if the exportType is XML.
089: * The ResultsJsp will use display the XML stored by this attribute. */
090: public static final String ATTRIBUTE_EXPORT_TYPE_XML = "org.jaffa.components.finder.FinderComponent.attributeExportTypeXml";
091:
092: // Properties
093: private Boolean m_displayResultsScreen = null;
094: private Boolean m_consolidatedCriteriaAndResults = null;
095: private String m_sortDropDown = null;
096: private String m_exportType = EXPORT_TYPE_WEB_PAGE;
097: private Integer m_maxRecords = new Integer(
098: ((Number) CriteriaDropDownOptions
099: .getDefaultMaxRecordsDropDownOption()).intValue());
100:
101: // Fields
102: private HeaderDto m_headerDto = null;
103: private FinderOutDto m_finderOutDto = null;
104:
105: // **************************************************************
106: // Component Properties
107: // **************************************************************
108:
109: /** Getter for property displayResultsScreen.
110: * @return Value of property displayResultsScreen.
111: */
112: public Boolean getDisplayResultsScreen() {
113: return m_displayResultsScreen;
114: }
115:
116: /** Setter for property displayResultsScreen.
117: * @param displayResultsScreen New value of property displayResultsScreen.
118: */
119: public void setDisplayResultsScreen(Boolean displayResultsScreen) {
120: m_displayResultsScreen = displayResultsScreen;
121: }
122:
123: /** Getter for property consolidatedCriteriaAndResults.
124: * @return Value of property consolidatedCriteriaAndResults.
125: */
126: public Boolean getConsolidatedCriteriaAndResults() {
127: return m_consolidatedCriteriaAndResults;
128: }
129:
130: /** Setter for property consolidatedCriteriaAndResults.
131: * @param consolidatedCriteriaAndResults New value of property consolidatedCriteriaAndResults.
132: */
133: public void setConsolidatedCriteriaAndResults(
134: Boolean consolidatedCriteriaAndResults) {
135: m_consolidatedCriteriaAndResults = consolidatedCriteriaAndResults;
136: }
137:
138: /** Getter for property sortDropDown.
139: * @return Value of property sortDropDown.
140: */
141: public String getSortDropDown() {
142: return m_sortDropDown;
143: }
144:
145: /** Setter for property sortDropDown.
146: * @param sortDropDown New value of property sortDropDown.
147: */
148: public void setSortDropDown(String sortDropDown) {
149: m_sortDropDown = sortDropDown;
150: }
151:
152: /** Getter for property exportType.
153: * @return Value of property exportType.
154: */
155: public String getExportType() {
156: return m_exportType;
157: }
158:
159: /** Setter for property exportType.
160: * @param exportType New value of property exportType.
161: */
162: public void setExportType(String exportType) {
163: m_exportType = exportType;
164: }
165:
166: /** Getter for property maxRecords.
167: * @return Value of property maxRecords.
168: */
169: public Integer getMaxRecords() {
170: return m_maxRecords;
171: }
172:
173: /** Setter for property maxRecords.
174: * @param maxRecords New value of property maxRecords.
175: */
176: public void setMaxRecords(Integer maxRecords) {
177: m_maxRecords = maxRecords;
178: }
179:
180: // **************************************************************
181: // Additional methods
182: // **************************************************************
183:
184: /** If the displayResultsScreen property has not been set or has been set to false, it will return the FormKey for the Criteria screen.
185: * If the displayResultsScreen property has been set to true, then a Search will be performed & the FormKey for the Results screen will be returned.
186: * @throws ApplicationExceptions This will be thrown in case any invalid data has been set.
187: * @throws FrameworkException Indicates some system error.
188: * @return The FormKey for the Criteria screen.
189: */
190: public FormKey display() throws ApplicationExceptions,
191: FrameworkException {
192: if (getDisplayResultsScreen() != null
193: && getDisplayResultsScreen().booleanValue())
194: return displayResults();
195: else
196: return displayCriteria();
197: }
198:
199: /** Invoked the initializeCriteriaScreen() method and then returns the FormKey for the Criteria screen.
200: * @throws ApplicationExceptions This will be thrown in case any invalid data has been set.
201: * @throws FrameworkException Indicates some system error.
202: * @return The FormKey for the Criteria screen.
203: */
204: public FormKey displayCriteria() throws ApplicationExceptions,
205: FrameworkException {
206: initializeCriteriaScreen();
207: return getCriteriaFormKey();
208: }
209:
210: /** Invokes the performInquiry() method and then returns the FormKey for the Results screen.
211: * If the consolidatedCriteriaAndResults property has been set to true, then the FormKey for consolidatedCriteriaAndResults screen will be returned.
212: * @throws ApplicationExceptions This will be thrown in case any invalid data has been set.
213: * @throws FrameworkException Indicates some system error.
214: * @return The FormKey for the Results screen.
215: */
216: public FormKey displayResults() throws ApplicationExceptions,
217: FrameworkException {
218: performInquiry();
219: return getResultsFormKey();
220: }
221:
222: /** Invokes the doInquiry() method and then removes the "rows" GridModel object from the cache.
223: * @throws ApplicationExceptions This will be thrown in case any invalid data has been set.
224: * @throws FrameworkException Indicates some system error.
225: */
226: public void performInquiry() throws ApplicationExceptions,
227: FrameworkException {
228: m_finderOutDto = doInquiry();
229: uncacheRowsModel();
230: }
231:
232: /** Getter for the Criteria screen's FormKey.
233: * @return the FormKey for the Criteria screen.
234: */
235: public FormKey getCriteriaFormKey() {
236: return new FormKey(getCriteriaFormName(), getComponentId());
237: }
238:
239: /** Getter for the Results screen's FormKey.
240: * @return the FormKey for the Results screen.
241: */
242: public FormKey getResultsFormKey() {
243: if (EXPORT_TYPE_EXCEL.equals(getExportType()))
244: return new FormKey(getExcelFormName(), getComponentId());
245: else if (EXPORT_TYPE_XML.equals(getExportType()))
246: return new FormKey(getXmlFormName(), getComponentId());
247: else if (getConsolidatedCriteriaAndResults() != null
248: && getConsolidatedCriteriaAndResults().booleanValue())
249: return new FormKey(
250: getConsolidatedCriteriaAndResultsFormName(),
251: getComponentId());
252: else
253: return new FormKey(getResultsFormName(), getComponentId());
254: }
255:
256: /** Getter for property finderOutDto.
257: * @return Value of property finderOutDto.
258: */
259: public FinderOutDto getFinderOutDto() {
260: return m_finderOutDto;
261: }
262:
263: /** This will set the property 'maxRecords' to the value following the current one, in the list of values returned by CriteriaDropDownOptions.getMaxRecordsDropDownOptions().
264: */
265: public void incrementMaxRecords() {
266: int currentValue = m_maxRecords != null ? m_maxRecords
267: .intValue() : 0;
268: for (Iterator i = CriteriaDropDownOptions
269: .getMaxRecordsDropDownOptions().keySet().iterator(); i
270: .hasNext();) {
271: int dropDownValue = ((Number) i.next()).intValue();
272: if (m_maxRecords == null) {
273: m_maxRecords = new Integer(dropDownValue);
274: updateMaxRecordsModel();
275: break;
276: } else if (currentValue == dropDownValue) {
277: if (i.hasNext()) {
278: m_maxRecords = new Integer(((Number) i.next())
279: .intValue());
280: updateMaxRecordsModel();
281: }
282: break;
283: }
284: }
285: }
286:
287: /** The Component should override this method to retrieve the set of codes for dropdowns in criteria screen, if any are required.
288: * @throws ApplicationExceptions This will be thrown in case any invalid data has been set.
289: * @throws FrameworkException Indicates some system error.
290: */
291: protected void initializeCriteriaScreen()
292: throws ApplicationExceptions, FrameworkException {
293: }
294:
295: /** Returns the HeaderDto. This can be used for passing the header info to the Tx, where required.
296: * @return the HeaderDto.
297: */
298: protected HeaderDto getHeaderDto() {
299: if (m_headerDto == null) {
300: m_headerDto = new HeaderDto();
301: m_headerDto.setUserId(getUserSession().getUserId());
302: m_headerDto.setVariation(VariationContext.getVariation());
303: }
304: return m_headerDto;
305: }
306:
307: /** Interprets the value of the 'sortDropDown' property adding suitable values to the input Dto.
308: * @param inputDto The Dto to which the orderby fields will be added.
309: */
310: protected void addSortCriteria(FinderInDto inputDto) {
311: if (getSortDropDown() != null) {
312: // these variables will be used while interpreting the sort field
313: String token = null;
314: boolean startOfField = true;
315: String field = null;
316: Boolean isAscending = null;
317:
318: StringTokenizer str = new StringTokenizer(
319: getSortDropDown(), " ,", true);
320: while (str.hasMoreTokens()) {
321: token = str.nextToken();
322: if (token.equals(COMMA)) {
323: // check for an existing field
324: if (field != null) {
325: if (isAscending != null)
326: inputDto.addOrderByFields(new OrderByField(
327: field, isAscending));
328: else
329: inputDto.addOrderByFields(new OrderByField(
330: field));
331: // reset the fields
332: field = null;
333: isAscending = null;
334: }
335: startOfField = true;
336: } else if (token.equals(SPACE)) {
337: // do nothing
338: } else if (startOfField) {
339: field = token;
340: startOfField = false;
341: } else {
342: if (token.toUpperCase().equals(DESC))
343: isAscending = Boolean.FALSE;
344: else
345: isAscending = Boolean.TRUE;
346: if (field != null) {
347: if (isAscending != null)
348: inputDto.addOrderByFields(new OrderByField(
349: field, isAscending));
350: else
351: inputDto.addOrderByFields(new OrderByField(
352: field));
353: // reset the fields
354: field = null;
355: isAscending = null;
356: }
357: }
358: }
359: // one final check
360: if (field != null) {
361: if (isAscending != null)
362: inputDto.addOrderByFields(new OrderByField(field,
363: isAscending));
364: else
365: inputDto.addOrderByFields(new OrderByField(field));
366: }
367: }
368: }
369:
370: /** Update the DropDownModel for the MaxRecords field, if one already exists. */
371: protected void updateMaxRecordsModel() {
372: DropDownModel wm = (DropDownModel) getUserSession()
373: .getWidgetCache(getComponentId()).getModel(
374: FinderForm.MAX_RECORDS);
375: if (wm != null)
376: DropDownController.updateModel(m_maxRecords.toString(), wm);
377: }
378:
379: /** Removes the 'rows' GridModel from the WidgetCache.
380: */
381: protected void uncacheRowsModel() {
382: getUserSession().getWidgetCache(getComponentId()).removeModel(
383: FinderForm.ROWS);
384: }
385:
386: /** The Component should provide an implementation for this method to perform the actual query to obtain the FinderOutDto.
387: * @throws ApplicationExceptions This will be thrown in case any invalid data has been set.
388: * @throws FrameworkException Indicates some system error.
389: * @return the FinderOutDto object.
390: */
391: protected abstract FinderOutDto doInquiry()
392: throws ApplicationExceptions, FrameworkException;
393:
394: /** The Component should provide an implementation for this method to return the Struts GlobalForward for the Criteria screen.
395: * @return the Struts GlobalForward for the Criteria screen.
396: */
397: protected abstract String getCriteriaFormName();
398:
399: /** The Component should provide an implementation for this method to return the Struts GlobalForward for the Results screen.
400: * @return the Struts GlobalForward for the Results screen.
401: */
402: protected abstract String getResultsFormName();
403:
404: /** The Component should provide an implementation for this method to return the Struts GlobalForward for the ConsolidatedCriteriaAndResults screen.
405: * @return the Struts GlobalForward for the ConsolidatedCriteriaAndResults screen.
406: */
407: protected abstract String getConsolidatedCriteriaAndResultsFormName();
408:
409: /** The Component should provide an implementation for this method to return the Struts GlobalForward for the screen displaying the results as an Excel spreadsheet.
410: * @return the Struts GlobalForward for the screen displaying the results as an Excel spreadsheet.
411: */
412: protected abstract String getExcelFormName();
413:
414: /** The Component should provide an implementation for this method to return the Struts GlobalForward for the screen displaying the results in XML format.
415: * @return the Struts GlobalForward for the screen displaying the results in XML format.
416: */
417: protected abstract String getXmlFormName();
418: }
|