001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
004: * All rights reserved.
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * $Id: Mapping.java,v 1.2 2006/09/29 12:32:08 drmlipp Exp $
021: *
022: * $Log: Mapping.java,v $
023: * Revision 1.2 2006/09/29 12:32:08 drmlipp
024: * Consistently using WfMOpen as projct name now.
025: *
026: * Revision 1.1.1.1 2003/06/30 20:05:12 drmlipp
027: * Initial import
028: *
029: * Revision 1.17 2003/06/27 08:51:46 lipp
030: * Fixed copyright/license information.
031: *
032: * Revision 1.16 2003/04/24 20:50:13 lipp
033: * Fixed some warnings.
034: *
035: * Revision 1.15 2003/03/31 16:50:28 huaiyang
036: * Logging using common-logging.
037: *
038: * Revision 1.14 2002/06/10 20:52:45 lipp
039: * Removed intermediate cocoon2 code.
040: *
041: * Revision 1.13 2002/06/08 12:15:29 lipp
042: * Removed cocoon2 add-ons, now in a new separate class.
043: *
044: * Revision 1.12 2002/06/03 11:57:24 huaiyang
045: * New methods for Cocoon 2 added.
046: *
047: * Revision 1.11 2002/04/26 09:03:36 huaiyang
048: * Correct javadoc error.
049: *
050: * Revision 1.10 2002/04/25 16:03:32 huaiyang
051: * Modify the method of generateMapping using contentHandler of Cocoon.
052: *
053: * Revision 1.9 2002/04/17 12:51:28 lipp
054: * Upgraded to jdom beta 8.
055: *
056: * Revision 1.8 2002/04/16 12:10:37 huaiyang
057: * Add new method of generateMappings using jdom.
058: *
059: * Revision 1.7 2002/04/03 12:53:04 lipp
060: * JavaDoc fixes.
061: *
062: * Revision 1.6 2002/02/06 20:43:51 lipp
063: * Optimized by introducing cache.
064: *
065: * Revision 1.5 2002/01/26 19:45:39 lipp
066: * SegmentedResourceBundle finally replaced by SegmentedMap.
067: *
068: * Revision 1.4 2002/01/17 16:41:48 lipp
069: * Fixed classloader
070: *
071: * Revision 1.3 2002/01/11 12:13:14 robert
072: * cleanup not needed import statements
073: *
074: * Revision 1.2 2001/12/04 15:37:07 lipp
075: * Comment fixed.
076: *
077: * Revision 1.1 2001/12/04 08:31:19 lipp
078: * Class de.danet.an.util.Mapping moved to subpackage web.
079: *
080: * Revision 1.3 2001/11/12 16:06:35 montag
081: * class documentation revised.
082: *
083: * Revision 1.2 2001/11/12 15:22:41 montag
084: * mapping handling for basename changed
085: *
086: * Revision 1.1 2001/11/12 14:52:58 montag
087: * redesign webclients
088: */
089: package de.danet.an.util.web;
090:
091: import java.util.Locale;
092: import java.util.List;
093: import java.util.Map;
094: import java.util.HashMap;
095: import java.util.Iterator;
096: import java.util.ResourceBundle;
097:
098: import javax.servlet.http.HttpSession;
099: import org.w3c.dom.Document;
100: import org.w3c.dom.DocumentFragment;
101: import org.w3c.dom.Element;
102: import de.danet.an.util.ResourceBundleAsMap;
103: import de.danet.an.util.SegmentedMap;
104: import de.danet.an.util.web.W3CDomUtil;
105:
106: /**
107: * Base class, implementing the methods used in logic sheet(s).
108: * The mathods in this class can be used to support an internationalization
109: * of texts and error messages in xsp pages.<p>
110: * Together with the logicsheet <code>mapping.xsl</code>, to use the
111: * functionality the followng steps must be fullfilled:
112: * <ul>
113: * <li>Include the logicsheet <code>mapping.xsl</code> in your own logicsheet
114: * for processing the xsp page.</li>
115: * <li> In your logicsheet, include the following match-rules:
116: * <pre> <xsl:template match="page">
117: * <page>
118: * <xsp:logic>
119: * if (session == null) {
120: * session = request.getSession (true);
121: * }
122: * session.setAttribute ("errorList", new ArrayList (1));
123: * </xsp:logic>
124: * <xsl:apply-templates/>
125: * <xsp:logic>
126: * xspCurrentNode.appendChild
127: * (Mapping.createErrorList(session, document));
128: * </xsp:logic>
129: * </page>
130: * </xsl:template>
131: *
132: * <xsl:template match="xsp:page">
133: * <xsp:page>
134: * <xsl:apply-templates select="@*"/>
135: * <xsp:structure>
136: * <xsp:include>
137: * de.danet.an.util.Mapping
138: * </xsp:include>
139: * </xsp:structure>
140: * <xsl:apply-templates/>
141: * </xsp:page>
142: * </xsl:template>
143: * </pre></li>
144: * <li>Define an I18n.properties file for your application.</li>
145: * <li> In your xsp page, you can now use the mapping functionality, e.g.
146: * <pre><mapping:generate_mappings key="staff.group.list"
147: * basename="de.danet.an.staffmgmt.webclient.I18n"/>
148: * </pre></li>
149: * <li>In your Java classes, where you encapsulate the logic code, you
150: * can set error texts like this:
151: * <pre>Mapping.mapError (session, "de.danet.an.staffmgmt.webclient.I18n",
152: * "error.staff.addGroupOption");
153: * </pre></li>
154: * </ul>
155: */
156: public class Mapping {
157:
158: private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
159: .getLog(Mapping.class);
160:
161: private static Map mapMap = new HashMap();
162:
163: private static SegmentedMap getMap(String baseName, Locale loc) {
164: String key = baseName + "@" + loc.toString();
165: synchronized (mapMap) {
166: SegmentedMap res = (SegmentedMap) mapMap.get(key);
167: if (res != null) {
168: return res;
169: }
170: ResourceBundle bundle = ResourceBundle.getBundle(baseName,
171: Locale.getDefault(), Thread.currentThread()
172: .getContextClassLoader());
173: res = new SegmentedMap(new ResourceBundleAsMap(bundle));
174: mapMap.put(key, res);
175: return res;
176: }
177: }
178:
179: /**
180: * Generates mapping entries for a given <code>key</code>.
181: * The mapping entries are taken from a language specific resource file.
182: * The given segment name is removed from the resulting keys.
183: * @param session the http session
184: * @param doc document, handed over by the cocoon framework
185: * @param baseName file name of resource bundle
186: * @param segment prefix for selecting the resource segment
187: * @return Document fragment with mapping nodes
188: */
189: public static DocumentFragment generateMappings(
190: HttpSession session, Document doc, String baseName,
191: String segment) {
192: // Get new document fragment
193: DocumentFragment frag = doc.createDocumentFragment();
194:
195: // Create mapping entries
196: SegmentedMap map = getMap(baseName, Locale.getDefault());
197: for (Iterator i = map.keySet(segment).iterator(); i.hasNext();) {
198: String key = (String) i.next();
199: Element mapping = doc.createElement("mapping");
200: // Remove segment name + "." from path
201: mapping.setAttribute("key", key
202: .substring(segment.length() + 1));
203: mapping.appendChild(doc.createTextNode((String) map
204: .get(key)));
205: frag.appendChild(mapping);
206: }
207: return frag;
208:
209: }
210:
211: /**
212: * Returns the i18n text for a given <code>key</code>.
213: * The text is based on the language settings
214: * of the user.
215: * @param session currently not used. May be used to get information
216: * about the user's locale.
217: * @param baseName Family name of the resource bundle
218: * @param key key for the text
219: * @return translated key, representing the language specific translation
220: */
221: public static String mapText(HttpSession session, String baseName,
222: String key) {
223: // get current message mapping setup and map key
224: SegmentedMap map = getMap(baseName, Locale.getDefault());
225: return ((String) map.get(key));
226: }
227:
228: /**
229: * Add an error message to the error list.
230: * @param session the http session.
231: * @param msg the error message.
232: */
233: public static void addError(HttpSession session, String msg) {
234: List errs = (List) session.getAttribute("errorList");
235: errs.add(msg);
236: }
237:
238: /**
239: * Add the error message referenced by a key to the error list.
240: * @param session the http session.
241: * @param baseName Family name of the resource bundle
242: * @param key the key of the error message.
243: */
244: public static void mapError(HttpSession session, String baseName,
245: String key) {
246: List errs = (List) session.getAttribute("errorList");
247: errs.add(mapText(session, baseName, key));
248: }
249:
250: /**
251: * Convert the errors accumulated to an XML structure.
252: * @param session the http session.
253: * @param doc document, handed over by the cocoon framework.
254: * @return Document fragment with error list.
255: */
256: public static DocumentFragment createErrorList(HttpSession session,
257: Document doc) {
258: // Get new document fragment
259: DocumentFragment frag = doc.createDocumentFragment();
260:
261: List errs = (List) session.getAttribute("errorList");
262: if (errs.size() == 0) {
263: return frag;
264: }
265: Element listNode = doc.createElement("errors");
266: W3CDomUtil.appendDialogHint(listNode, null, "list");
267: for (Iterator i = errs.iterator(); i.hasNext();) {
268: String s = (String) i.next();
269: Element el = doc.createElement("error");
270: el.appendChild(doc.createTextNode(s));
271: listNode.appendChild(el);
272: }
273: frag.appendChild(listNode);
274: return frag;
275: }
276:
277: }
|