001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: package com.jcorporate.expresso.ext.velocity;
066:
067: import com.jcorporate.expresso.core.controller.Block;
068: import com.jcorporate.expresso.core.controller.ControllerElement;
069: import com.jcorporate.expresso.core.controller.ControllerException;
070: import com.jcorporate.expresso.core.controller.ControllerResponse;
071: import com.jcorporate.expresso.core.db.DBException;
072: import com.jcorporate.expresso.core.i18n.Messages;
073: import com.jcorporate.expresso.services.dbobj.SchemaList;
074:
075: import java.util.List;
076: import java.util.StringTokenizer;
077:
078: /**
079: * A generic object that allows Velocity pages to be written more user friendly.
080: *
081: * @author David Lloyd
082: * <p/>
083: * <p/>
084: * <p/>
085: * $Log: ExpressoTool.java,v $
086: * Revision 1.5 2004/11/18 02:03:29 lhamel
087: * cosmetic reformat
088: *
089: * Revision 1.4 2004/11/17 20:48:16 lhamel
090: * cosmetic reformat
091: * <p/>
092: * Revision 1.3 2004/09/29 07:05:01 mtraum
093: * added license to source files
094: * <p/>
095: * Revision 1.2 2004/09/22 05:11:55 mtraum
096: * organize imports
097: * <p/>
098: * Revision 1.1 2004/05/29 16:51:31 dlloyd
099: * Initial checkin of velocity support
100: */
101:
102: public class ExpressoTool {
103:
104: /**
105: * Return a string in the messages bundles. The current schema stack is seached for the
106: * <p/>
107: * correct translation. This is a wrapper for Messages.getString(stack,locale,code,args).
108: *
109: * @param response The controllerResponse request attribute that contains the schema stack.
110: * @param code The string code being searched for.
111: * @param args Any replacement arguments; can be null.
112: * @return The code translation if found, otherwise the code itself.
113: */
114:
115: public String getString(ControllerResponse response, String code,
116: List args) throws ControllerException {
117:
118: Object[] argsArray;
119:
120: if (args == null) {
121: argsArray = new Object[0];
122: } else {
123: argsArray = args.toArray();
124: }
125:
126: return Messages.getString(response.getSchemaStack(),
127:
128: response.getLocale(),
129:
130: code,
131:
132: argsArray);
133:
134: }
135:
136: /**
137: * Find a <code>ControllerElement</code> in the response identified by a path.
138: * <p/>
139: * This path is somewhat similar to the paths used in the taglibs. The differences
140: * <p/>
141: * are that a leading '/' means start from the controller response and a '@' means
142: * <p/>
143: * to return the string which is the attribute by the name that follows. Also, if
144: * <p/>
145: * the path item name cannot be found and the name starts with one of 'BLOCK:',
146: * <p/>
147: * 'OUTPUT:', 'INPUT:', or 'TRANSITION:', then the prefix is removed and the search
148: * <p/>
149: * is made again limited to the type of object specified.
150: * <p/>
151: * <p/>
152: * <p/>
153: * <p><pre>
154: * <p/>
155: * An example use in Velocity:
156: * <p/>
157: * #exp_element( $myelement "lists/groups/tests" )
158: * <p/>
159: * returns the element named 'tests'
160: * <p/>
161: * <p/>
162: * <p/>
163: * #exp_element( $myelement "lists/BLOCK:groups/tests" )
164: * <p/>
165: * returns the same element named 'tests' as above but useful if
166: * <p/>
167: * an object named groups exists in transitions (for example).
168: * <p/>
169: * <p/>
170: * <p/>
171: * #exp_element( $myelement "lists/groups/@style" )
172: * <p/>
173: * returns the string for attribute 'style' in 'groups'
174: * <p/>
175: * </pre>
176: *
177: * @param response The controllerResponse request attribute.
178: * @param path The path to the element or attribute to be returned.
179: * @return The found object or null.
180: */
181:
182: public Object getElement(ControllerResponse response, String path)
183: throws ControllerException {
184:
185: if (path == null || path.length() == 0) {
186: return null;
187: }
188:
189: if (path.charAt(0) == '/') {
190: if (path.length() == 1) {
191: return null;
192: } else {
193: path = path.substring(1);
194: }
195: }
196:
197: Object element = null;
198:
199: StringTokenizer tok = new StringTokenizer(path, "/");
200:
201: if (tok.hasMoreTokens()) {
202:
203: String token = tok.nextToken().trim();
204:
205: boolean isAttribute = false;
206:
207: if (token.length() > 1) {
208:
209: if (token.charAt(0) == '@') {
210:
211: isAttribute = true;
212:
213: token = token.substring(1);
214:
215: }
216:
217: }
218:
219: if (token.length() != 0) {
220:
221: if (isAttribute) {
222:
223: return response.getAttribute(token);
224:
225: } else {
226:
227: element = response.getNestedMap().get(token);
228:
229: if (element == null) {
230:
231: if (token.startsWith("BLOCK:")) {
232:
233: element = response.getBlock(token
234: .substring(6));
235:
236: } else if (token.startsWith("OUTPUT:")) {
237:
238: element = response.getBlock(token
239: .substring(7));
240:
241: } else if (token.startsWith("INPUT:")) {
242:
243: element = response.getBlock(token
244: .substring(6));
245:
246: } else if (token.startsWith("TRANSITION:")) {
247:
248: element = response.getBlock(token
249: .substring(11));
250:
251: }
252:
253: }
254:
255: }
256:
257: }
258:
259: if (tok.hasMoreTokens()) {
260:
261: element = getElementFrom(response,
262: (ControllerElement) element, tok);
263:
264: }
265:
266: }
267:
268: return element;
269:
270: }
271:
272: /**
273: * Find a <code>ControllerElement</code> in the response identified by a path.
274: * <p/>
275: * This path is somewhat similar to the paths used in the taglibs. The differences
276: * <p/>
277: * are that a leading '/' means start from the controller response and a '@' means
278: * <p/>
279: * to return the string which is the attribute by the name that follows. Also, if
280: * <p/>
281: * the path item name cannot be found and the name starts with one of 'BLOCK:',
282: * <p/>
283: * 'OUTPUT:', 'INPUT:', or 'TRANSITION:', then the prefix is removed and the search
284: * <p/>
285: * is made again limited to the type of object specified. If the from parameter is null
286: * <p/>
287: * or the path starts with a '/' then this function behaves the same as
288: * <p/>
289: * getElement(response, path).
290: * <p/>
291: * <p/>
292: * <p/>
293: * <p><pre>
294: * <p/>
295: * An example use in Velocity:
296: * <p/>
297: * #exp_elementFrom( $myelement $fromElement "lists/groups/tests" )
298: * <p/>
299: * returns the element named 'tests'
300: * <p/>
301: * <p/>
302: * <p/>
303: * #exp_element( $myelement $fromElement "lists/BLOCK:groups/tests" )
304: * <p/>
305: * returns the same element named 'tests' as above but useful if
306: * <p/>
307: * an object named groups exists in transitions (for example).
308: * <p/>
309: * <p/>
310: * <p/>
311: * #exp_element( $myelement $fromElement "lists/groups/@style" )
312: * <p/>
313: * returns the string for attribute 'style' in 'groups'
314: * <p/>
315: * </pre>
316: *
317: * @param response The controllerResponse request attribute.
318: * @param path The path to the element or attribute to be returned.
319: * @param from The ControllerElement to start the search from.
320: * @return The found object or null.
321: */
322:
323: public Object getElementFrom(ControllerResponse response,
324: ControllerElement from, String path)
325: throws ControllerException {
326:
327: if (from == null) {
328: return getElement(response, path);
329: }
330:
331: if (path == null || path.length() == 0) {
332: return from;
333: }
334:
335: if (path.charAt(0) == '/') {
336: return getElement(response, path);
337: }
338:
339: StringTokenizer tok = new StringTokenizer(path, "/");
340:
341: Object element = getElementFrom(response, from, tok);
342:
343: return element;
344:
345: }
346:
347: private Object getElementFrom(ControllerResponse response,
348: ControllerElement from, StringTokenizer tok)
349: throws ControllerException {
350:
351: ControllerElement element = null;
352:
353: while (tok.hasMoreTokens()) {
354:
355: String token = tok.nextToken().trim();
356:
357: boolean isAttribute = false;
358:
359: if (token.length() > 1) {
360:
361: if (token.charAt(0) == '@') {
362:
363: isAttribute = true;
364:
365: token = token.substring(1);
366:
367: }
368:
369: }
370:
371: if (token.length() != 0) {
372:
373: if (isAttribute) {
374:
375: return from.getAttribute(token);
376:
377: } else {
378:
379: element = (ControllerElement) from.getNestedMap()
380: .get(token);
381:
382: if (element == null && (from instanceof Block)) {
383:
384: if (token.startsWith("BLOCK:")) {
385:
386: element = ((Block) from).getBlock(token
387: .substring(6));
388:
389: } else if (token.startsWith("OUTPUT:")) {
390:
391: element = ((Block) from).getBlock(token
392: .substring(7));
393:
394: } else if (token.startsWith("INPUT:")) {
395:
396: element = ((Block) from).getBlock(token
397: .substring(6));
398:
399: } else if (token.startsWith("TRANSITION:")) {
400:
401: element = ((Block) from).getBlock(token
402: .substring(11));
403:
404: }
405:
406: }
407:
408: if (element == null) {
409:
410: return null;
411:
412: } else {
413:
414: from = element;
415:
416: }
417:
418: }
419:
420: }
421:
422: }
423:
424: return from;
425:
426: }
427:
428: /**
429: * Get a value from the setup table. A simple wrapper for Setup.getValue(dataContext, key).
430: *
431: * @param dataContext The data context for the setup table.
432: * @param key The key whose value is to be retrieved.
433: * @return The found value or null
434: * @see com.jcorporate.expresso.services.dbobj.Setup
435: */
436:
437: public String getSetupValue(String dataContext, String key)
438: throws DBException {
439:
440: return com.jcorporate.expresso.services.dbobj.Setup.getValue(
441: dataContext, key);
442:
443: }
444:
445: /**
446: * Get the ConfigManager singleton.
447: *
448: * @return The ConfigManager singleton.
449: */
450:
451: public com.jcorporate.expresso.core.misc.ConfigManager getConfigManager() {
452:
453: return com.jcorporate.expresso.core.misc.ConfigManager
454: .getInstance();
455:
456: }
457:
458: /**
459: * Returns the list of installed schemas. This would commonly be used to support the
460: * <p/>
461: * current expresso tradition of listin the installed components in the left menu.
462: *
463: * @param dataContext The data context for SchemaList (typically 'default').
464: * @return The SchemaList.
465: */
466:
467: public List getSchemaList(String dataContext) throws DBException {
468:
469: SchemaList sl = new SchemaList(SchemaList.SYSTEM_ACCOUNT);
470:
471: sl.setDBName(dataContext);
472:
473: return sl.searchAndRetrieveList();
474:
475: }
476:
477: }
|