001: /*
002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/widgets/CmsLocalizationWidget.java,v $
003: * Date : $Date: 2008-02-27 12:05:44 $
004: * Version: $Revision: 1.4 $
005: *
006: * This library is part of OpenCms -
007: * the Open Source Content Management System
008: *
009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * For further information about Alkacon Software GmbH, please see the
022: * company website: http://www.alkacon.com
023: *
024: * For further information about OpenCms, please see the
025: * project website: http://www.opencms.org
026: *
027: * You should have received a copy of the GNU Lesser General Public
028: * License along with this library; if not, write to the Free Software
029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030: */
031:
032: package org.opencms.widgets;
033:
034: import org.opencms.file.CmsObject;
035: import org.opencms.i18n.CmsEncoder;
036: import org.opencms.i18n.CmsMessages;
037: import org.opencms.util.CmsMacroResolver;
038: import org.opencms.util.CmsStringUtil;
039: import org.opencms.util.I_CmsMacroResolver;
040: import org.opencms.xml.types.I_CmsXmlContentValue;
041:
042: import java.util.Iterator;
043: import java.util.List;
044: import java.util.Locale;
045: import java.util.Map;
046: import java.util.regex.Matcher;
047: import java.util.regex.Pattern;
048:
049: /**
050: * Provides a standard HTML form input widget for overwriting localized values of a resource bundle, for use on a widget dialog.<p>
051: *
052: * The resource bundle is configured with the widget configuration attribute. An optional key name to look up in the bundle
053: * can be given, too, in case it is different from the element name: <code>key=mykey</code>.<p>
054: *
055: * The locale to get the value for can be configured, too, by adding a configuration directive: <code>locale=en</code>.<p>
056: *
057: * Example: <code><layout element="elemname" widget="LocalizationWidget" configuration="org.opencms.workplace.messages|key=mykey|locale=en" /></code>.<p>
058: *
059: * To use the stored localization values and have the values of the resource bundles as fallback,
060: * use the {@link org.opencms.xml.CmsXmlMessages} object.<p>
061: *
062: * @author Andreas Zahner
063: *
064: * @version $Revision: 1.4 $
065: *
066: * @since 6.5.4
067: */
068: public class CmsLocalizationWidget extends A_CmsWidget {
069:
070: /** The option for the localized key name. */
071: public static final String OPTION_KEY = "key=";
072:
073: /** The option for the locale to use. */
074: public static final String OPTION_LOCALE = "locale=";
075:
076: /** Pattern to get OpenCms like macros, e.g. "%(0)". */
077: private static Pattern PATTERN_MACRO = Pattern.compile(".*("
078: + I_CmsMacroResolver.MACRO_DELIMITER + "\\"
079: + I_CmsMacroResolver.MACRO_START + ")(\\d*)(\\"
080: + I_CmsMacroResolver.MACRO_END + ").*");
081:
082: /** Pattern to get message bundle arguments, e.g. "{0}". */
083: private static Pattern PATTERN_MESSAGEARGUMENT = Pattern
084: .compile(".*(\\{)(\\d*)(\\}).*");
085:
086: /** The bundle key (optional, if not equal to the element name). */
087: private String m_bundleKey;
088:
089: /** The locale to get the value for. */
090: private Locale m_locale;
091:
092: /** The localized bundle to get the value from. */
093: private CmsMessages m_messages;
094:
095: /**
096: * Creates a new input localization widget.<p>
097: */
098: public CmsLocalizationWidget() {
099:
100: // empty constructor is required for class registration
101: this ("");
102: }
103:
104: /**
105: * Creates a new input localization widget with the given configuration.<p>
106: *
107: * @param configuration the configuration to use
108: */
109: public CmsLocalizationWidget(String configuration) {
110:
111: super (configuration);
112: }
113:
114: /**
115: * @see org.opencms.widgets.I_CmsWidget#getDialogWidget(org.opencms.file.CmsObject, org.opencms.widgets.I_CmsWidgetDialog, org.opencms.widgets.I_CmsWidgetParameter)
116: */
117: public String getDialogWidget(CmsObject cms,
118: I_CmsWidgetDialog widgetDialog, I_CmsWidgetParameter param) {
119:
120: String id = param.getId();
121: // initialize bundle
122: initConfiguration(cms, param);
123:
124: StringBuffer result = new StringBuffer(256);
125:
126: result.append("<td class=\"xmlTd\">");
127: result.append("<input class=\"xmlInput textInput");
128: if (param.hasError()) {
129: result.append(" xmlInputError");
130: }
131: result.append("\"");
132: result.append(" name=\"");
133: result.append(id);
134: result.append("\" id=\"");
135: result.append(id);
136: result.append("\" value=\"");
137:
138: // determine value to show in editor
139: String value = m_messages.key(m_bundleKey);
140: if ((CmsStringUtil.isNotEmptyOrWhitespaceOnly(param
141: .getStringValue(cms)) && !value.equals(param
142: .getStringValue(cms)))
143: || value.startsWith(CmsMessages.UNKNOWN_KEY_EXTENSION)) {
144: // saved value is provided and different from localized value in bundle or no value found in bundle, use it
145: value = param.getStringValue(cms);
146: // replace OpenCms macro syntax with message bundle arguments
147: Matcher matcher = PATTERN_MACRO.matcher(value);
148: while (matcher.matches()) {
149: int startIndex = matcher.start(1);
150: int endIndex = matcher.end(3);
151: String number = matcher.group(2);
152: value = value.substring(0, startIndex) + "{" + number
153: + "}" + value.substring(endIndex);
154: matcher = PATTERN_MACRO.matcher(value);
155: }
156:
157: }
158:
159: result.append(CmsEncoder.escapeXml(value));
160: result.append("\">");
161: result.append("</td>");
162:
163: return result.toString();
164: }
165:
166: /**
167: * @see org.opencms.widgets.I_CmsWidget#newInstance()
168: */
169: public I_CmsWidget newInstance() {
170:
171: return new CmsLocalizationWidget(getConfiguration());
172: }
173:
174: /**
175: * @see org.opencms.widgets.I_CmsWidget#setEditorValue(org.opencms.file.CmsObject, java.util.Map, org.opencms.widgets.I_CmsWidgetDialog, org.opencms.widgets.I_CmsWidgetParameter)
176: */
177: public void setEditorValue(CmsObject cms, Map formParameters,
178: I_CmsWidgetDialog widgetDialog, I_CmsWidgetParameter param) {
179:
180: String[] values = (String[]) formParameters.get(param.getId());
181: if ((values != null) && (values.length > 0)) {
182: // initialize bundle
183: initConfiguration(cms, param);
184: String value = m_messages.key(m_bundleKey);
185: if (value.equals(values[0].trim())) {
186: // value is equal to localized value, do not save
187: value = "";
188: } else {
189: // value is different, save it
190: value = values[0];
191: // now replace message bundle like argument placeholders like "{0}" with OpenCms macros
192: Matcher matcher = PATTERN_MESSAGEARGUMENT
193: .matcher(value);
194: while (matcher.matches()) {
195: int startIndex = matcher.start(1);
196: int endIndex = matcher.end(3);
197: String number = CmsMacroResolver
198: .formatMacro(matcher.group(2));
199: // replace arguments with macros
200: value = value.substring(0, startIndex) + number
201: + value.substring(endIndex);
202: matcher = PATTERN_MESSAGEARGUMENT.matcher(value);
203: }
204: }
205: param.setStringValue(cms, value);
206: }
207: }
208:
209: /**
210: * Initializes the localized bundle to get the value from, the optional key name and the optional locale.<p>
211: *
212: * @param cms an initialized instance of a CmsObject
213: * @param param the widget parameter to generate the widget for
214: */
215: protected void initConfiguration(CmsObject cms,
216: I_CmsWidgetParameter param) {
217:
218: // set the default bundle key
219: m_bundleKey = param.getName();
220: // set the default locale for XML contents
221: m_locale = cms.getRequestContext().getLocale();
222: try {
223: I_CmsXmlContentValue value = (I_CmsXmlContentValue) param;
224: m_locale = value.getLocale();
225: } catch (Exception e) {
226: // ignore, this is no XML content
227: }
228:
229: // check the message bundle
230: if (CmsStringUtil
231: .isNotEmptyOrWhitespaceOnly(getConfiguration())) {
232: //initialize messages, the optional bundle key name and the optional locale from configuration String
233: String bundleName = "";
234: List configs = CmsStringUtil.splitAsList(
235: getConfiguration(), '|');
236: Iterator i = configs.iterator();
237: while (i.hasNext()) {
238: String config = (String) i.next();
239: if (config.startsWith(OPTION_KEY)) {
240: m_bundleKey = config.substring(OPTION_KEY.length());
241: } else if (config.startsWith(OPTION_LOCALE)) {
242: m_locale = new Locale(config
243: .substring(OPTION_LOCALE.length()));
244: } else {
245: bundleName = config;
246: }
247: }
248: // create messages object
249: m_messages = new CmsMessages(bundleName, m_locale);
250: } else {
251: // initialize empty messages object to avoid NPE
252: m_messages = new CmsMessages("", m_locale);
253: }
254: }
255: }
|