001: /*
002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/workplace/CmsWidgetDialogParameter.java,v $
003: * Date : $Date: 2008-02-27 12:05:45 $
004: * Version: $Revision: 1.16 $
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.workplace;
033:
034: import org.opencms.file.CmsObject;
035: import org.opencms.main.CmsException;
036: import org.opencms.main.CmsIllegalArgumentException;
037: import org.opencms.main.CmsRuntimeException;
038: import org.opencms.util.CmsStringUtil;
039: import org.opencms.widgets.A_CmsWidget;
040: import org.opencms.widgets.CmsWidgetException;
041: import org.opencms.widgets.I_CmsWidget;
042: import org.opencms.widgets.I_CmsWidgetParameter;
043: import org.opencms.widgets.Messages;
044:
045: import java.lang.reflect.InvocationTargetException;
046: import java.util.ArrayList;
047: import java.util.List;
048: import java.util.SortedMap;
049:
050: import org.apache.commons.beanutils.ConvertUtilsBean;
051: import org.apache.commons.beanutils.PropertyUtilsBean;
052:
053: /**
054: * Implements the widget parameter interface for the use of OpenCms widgets on dialogs that
055: * are not based on XML contents.<p>
056: *
057: * @author Alexander Kandzior
058: *
059: * @version $Revision: 1.16 $
060: *
061: * @since 6.0.0
062: */
063: public class CmsWidgetDialogParameter implements I_CmsWidgetParameter {
064:
065: /** The name of the default dialog page. */
066: public static final String DEFAULT_DIALOG_PAGE = "default";
067:
068: /** The maximum number of occurences of a widget dialog element in a list of elements. */
069: public static final int MAX_OCCURENCES = 200;
070:
071: /** The (optional) base collection for read / writing collection based parameters. */
072: protected Object m_baseCollection;
073:
074: /** The (optional) base object for read / writing the parameter value to. */
075: protected Object m_baseObject;
076:
077: /** The (optinal) object property to read / write this parameter value to. */
078: protected String m_baseObjectProperty;
079:
080: /** The default value of the parameter. */
081: protected String m_defaultValue;
082:
083: /** The name of the dialog (page) the widget is used on. */
084: protected String m_dialogPage;
085:
086: /** Indicates if the widget value has an error. */
087: protected Throwable m_error;
088:
089: /** The id of the parameter on the form. */
090: protected String m_id;
091:
092: /** The index of this parameter in the (optional) list of parameters. */
093: protected int m_index;
094:
095: /** The maximum number of occurences of this parameter. */
096: protected int m_maxOccurs;
097:
098: /** The minimum number of occurences of this parameter. */
099: protected int m_minOccurs;
100:
101: /** The name of the parameter. */
102: protected String m_name;
103:
104: /** Optional localized key prefix identificator. */
105: protected String m_prefix;
106:
107: /** The value of the parameter. */
108: protected String m_value;
109:
110: /** The widget used for the parameter. */
111: protected I_CmsWidget m_widget;
112:
113: /**
114: * Create a new Widget parameter.<p>
115: *
116: * @param base the base of the parameter
117: * @param index the index of this parameter in the list
118: */
119: public CmsWidgetDialogParameter(CmsWidgetDialogParameter base,
120: int index) {
121:
122: this (null, base.m_defaultValue, base.getName(), base
123: .getWidget(), base.getDialogPage(),
124: base.getMinOccurs(), base.getMaxOccurs(), index);
125:
126: m_baseObject = base.m_baseObject;
127: m_baseObjectProperty = base.m_baseObjectProperty;
128: m_baseCollection = base.m_baseCollection;
129: m_prefix = base.m_prefix;
130: }
131:
132: /**
133: * Create a new Widget parameter.<p>
134: *
135: * @param base the base of the parameter
136: * @param index the index of this parameter in the list
137: * @param originalIndex the original index in the previous version of the list
138: */
139: public CmsWidgetDialogParameter(CmsWidgetDialogParameter base,
140: int index, int originalIndex) {
141:
142: this (null, base.m_defaultValue, base.getName(), base
143: .getWidget(), base.getDialogPage(),
144: base.getMinOccurs(), base.getMaxOccurs(), index);
145:
146: m_baseObject = base.m_baseObject;
147: m_baseObjectProperty = base.m_baseObjectProperty;
148: m_baseCollection = base.m_baseCollection;
149:
150: if (m_baseCollection != null) {
151: if (m_baseCollection instanceof List) {
152: // base object is a list - make sure to set possible old value
153: List baseList = (List) m_baseCollection;
154: if (originalIndex < baseList.size()) {
155: Object o = baseList.get(originalIndex);
156: if (o != null) {
157: m_value = o.toString();
158: }
159: }
160: } else if (m_baseCollection instanceof SortedMap) {
161: // base object is a sorted map - make sure to set possible old value
162: SortedMap baseMap = (SortedMap) m_baseCollection;
163: List keyList = new ArrayList(baseMap.keySet());
164: if (originalIndex < keyList.size()) {
165: Object key = keyList.get(originalIndex);
166: Object value = baseMap.get(key);
167: StringBuffer val = new StringBuffer();
168: val.append(key != null ? key.toString() : "");
169: val.append('=');
170: val.append(value != null ? value.toString() : "");
171: m_value = val.toString();
172: }
173: }
174: }
175: }
176:
177: /**
178: * Create a new Widget parameter based on a given object's property.<p>
179: *
180: * @param base the base object to map the parameter to / from
181: * @param property the base object property to map the parameter to / from
182: * @param widget the widget used for this parameter
183: */
184: public CmsWidgetDialogParameter(Object base, String property,
185: I_CmsWidget widget) {
186:
187: this (base, property, DEFAULT_DIALOG_PAGE, widget);
188: }
189:
190: /**
191: * Create a new Widget parameter based on a given object's property.<p>
192: *
193: * @param base the base object to map the parameter to / from
194: * @param property the base object property to map the parameter to / from
195: * @param dialogPage the dialog page to use the widget on
196: * @param widget the widget used for this parameter
197: */
198: public CmsWidgetDialogParameter(Object base, String property,
199: String dialogPage, I_CmsWidget widget) {
200:
201: this (base, property, null, dialogPage, widget, 1, 1);
202: }
203:
204: /**
205: * Create a new Widget parameter based on a given object's property.<p>
206: *
207: * @param base the base object to map the parameter to / from
208: * @param property the base object property to map the parameter to / from
209: * @param htmlName the form id name to use in the generated HTML
210: * @param dialogPage the dialog page to use the widget on
211: * @param widget the widget used for this parameter
212: *
213: */
214: public CmsWidgetDialogParameter(Object base, String property,
215: String htmlName, String dialogPage, I_CmsWidget widget) {
216:
217: this (base, property, htmlName, null, dialogPage, widget, 1, 1);
218: }
219:
220: /**
221: * Create a new Widget parameter based on a given object's property.<p>
222: *
223: * @param base the base object to map the parameter to / from
224: * @param property the base object property to map the parameter to / from
225: * @param defaultValue the default value to use for this parameter
226: * @param dialogPage the dialog page to use the widget on
227: * @param widget the widget used for this paramete
228: * @param minOccurs the required minimum numer of occurences of this parameter
229: * @param maxOccurs the maximum allowed numer of occurences of this parameter
230: */
231: public CmsWidgetDialogParameter(Object base, String property,
232: String defaultValue, String dialogPage, I_CmsWidget widget,
233: int minOccurs, int maxOccurs) {
234:
235: this (base, property, property, defaultValue, dialogPage,
236: widget, minOccurs, maxOccurs);
237: }
238:
239: /**
240: * Create a new Widget parameter based on a given object's property.<p>
241: *
242: * @param base the base object to map the parameter to / from
243: * @param property the base object property to map the parameter to / from
244: * @param htmlName the form id name to use in the generated HTML
245: * @param defaultValue the default value to use for this parameter
246: * @param dialogPage the dialog page to use the widget on
247: * @param widget the widget used for this paramete
248: * @param minOccurs the required minimum numer of occurences of this parameter
249: * @param maxOccurs the maximum allowed numer of occurences of this parameter
250: */
251: public CmsWidgetDialogParameter(Object base, String property,
252: String htmlName, String defaultValue, String dialogPage,
253: I_CmsWidget widget, int minOccurs, int maxOccurs) {
254:
255: if (htmlName == null) {
256: htmlName = property;
257: }
258:
259: if ((base instanceof List) || (base instanceof SortedMap)) {
260:
261: // this is a list, use custom list mappings
262: init(null, defaultValue, htmlName, widget, dialogPage, 0,
263: MAX_OCCURENCES, 0);
264:
265: m_baseObject = null;
266: m_baseObjectProperty = null;
267: m_baseCollection = base;
268:
269: } else {
270:
271: // generic object:use reflection to map object properties
272: init(null, defaultValue, htmlName, widget, dialogPage,
273: minOccurs, maxOccurs, 0);
274:
275: m_baseObject = base;
276: m_baseObjectProperty = property;
277: m_baseCollection = null;
278:
279: PropertyUtilsBean bean = new PropertyUtilsBean();
280:
281: Object value = null;
282: // make sure the base object has the requested property
283: if (!bean.isReadable(m_baseObject, m_baseObjectProperty)
284: || !bean.isWriteable(m_baseObject,
285: m_baseObjectProperty)) {
286: try {
287: // check if this is a mapped property
288: value = bean.getMappedProperty(m_baseObject,
289: m_baseObjectProperty);
290: } catch (Exception e) {
291: throw new CmsIllegalArgumentException(
292: Messages.get()
293: .container(
294: Messages.ERR_NO_PROPERTY_2,
295: base.getClass().getName(),
296: property));
297: }
298: }
299:
300: try {
301: if (value == null) {
302: // may have been read already as a mapped property
303: value = bean.getNestedProperty(m_baseObject,
304: m_baseObjectProperty);
305: }
306: } catch (Exception e) {
307: throw new CmsRuntimeException(Messages.get().container(
308: Messages.ERR_PROPERTY_READ_2, property,
309: base.getClass().getName()), e);
310: }
311:
312: if (value != null) {
313: if ((value instanceof List)
314: || (value instanceof SortedMap)) {
315: m_baseCollection = value;
316: m_minOccurs = 0;
317: m_maxOccurs = MAX_OCCURENCES;
318: } else {
319: m_defaultValue = String.valueOf(value);
320: m_value = m_defaultValue;
321: if ((m_minOccurs == 0)
322: && !m_value.equals(defaultValue)) {
323: // if value is different from default ensure this widget is displayed
324: m_minOccurs = 1;
325: }
326: }
327: }
328: }
329: }
330:
331: /**
332: * Create a new Widget parameter.<p>
333: *
334: * @param name the name of the parameter
335: * @param widget the widget used for this parameter
336: */
337: public CmsWidgetDialogParameter(String name, I_CmsWidget widget) {
338:
339: this (null, null, name, widget, DEFAULT_DIALOG_PAGE, 1, 1, 0);
340: }
341:
342: /**
343: * Create a new Widget parameter.<p>
344: *
345: * @param name the name of the parameter
346: * @param widget the widget used for this parameter
347: * @param minOccurs the required minimum numer of occurences of this parameter
348: * @param maxOccurs the maximum allowed numer of occurences of this parameter
349: */
350: public CmsWidgetDialogParameter(String name, I_CmsWidget widget,
351: int minOccurs, int maxOccurs) {
352:
353: this (null, null, name, widget, DEFAULT_DIALOG_PAGE, minOccurs,
354: maxOccurs, 0);
355: }
356:
357: /**
358: * Create a new Widget parameter with specified occurence settings.<p>
359: *
360: * @param value the initial value of the parameter
361: * @param defaultValue the default value of the parameter
362: * @param name the id of the parameter
363: * @param widget the widget used for this parameter
364: * @param dialog the dialog this parameter is used on
365: * @param minOccurs the required minimum numer of occurences of this parameter
366: * @param maxOccurs the maximum allowed numer of occurences of this parameter
367: * @param index the index of this parameter in the list
368: */
369: public CmsWidgetDialogParameter(String value, String defaultValue,
370: String name, I_CmsWidget widget, String dialog,
371: int minOccurs, int maxOccurs, int index) {
372:
373: super ();
374: init(value, defaultValue, name, widget, dialog, minOccurs,
375: maxOccurs, index);
376: }
377:
378: /**
379: * Returns a from id representation for the given widget name and id.<p>
380: *
381: * @param name the widget parameter name
382: * @param index the widget parameter index
383: *
384: * @return a from id representation for the given widget name and id
385: */
386: public static String createId(String name, int index) {
387:
388: StringBuffer result = new StringBuffer();
389: result.append(name);
390: result.append('.');
391: result.append(index);
392:
393: return result.toString();
394: }
395:
396: /**
397: * "Commits" (writes) the value of this widget back to the underlying base object.<p>
398: *
399: * @param dialog the widget dialog where the parameter is used on
400: *
401: * @throws CmsException in case the String value of the widget is invalid for the base Object
402: */
403: public void commitValue(CmsWidgetDialog dialog) throws CmsException {
404:
405: if (m_baseCollection == null) {
406: PropertyUtilsBean bean = new PropertyUtilsBean();
407: ConvertUtilsBean converter = new ConvertUtilsBean();
408: Object value = null;
409: try {
410: Class type = bean.getPropertyType(m_baseObject,
411: m_baseObjectProperty);
412: value = converter.convert(m_value, type);
413: bean.setNestedProperty(m_baseObject,
414: m_baseObjectProperty, value);
415: setError(null);
416: } catch (InvocationTargetException e) {
417: setError(e.getTargetException());
418: throw new CmsWidgetException(Messages.get().container(
419: Messages.ERR_PROPERTY_WRITE_3,
420: value,
421: dialog
422: .keyDefault(A_CmsWidget
423: .getLabelKey(this ), getKey()),
424: m_baseObject.getClass().getName()), e
425: .getTargetException(), this );
426: } catch (Exception e) {
427: setError(e);
428: throw new CmsWidgetException(Messages.get().container(
429: Messages.ERR_PROPERTY_WRITE_3,
430: value,
431: dialog
432: .keyDefault(A_CmsWidget
433: .getLabelKey(this ), getKey()),
434: m_baseObject.getClass().getName()), e, this );
435: }
436: } else if (m_baseCollection instanceof SortedMap) {
437: if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_value)) {
438: int pos = m_value.indexOf('=');
439: if ((pos > 0) && (pos < (m_value.length() - 1))) {
440: String key = m_value.substring(0, pos);
441: String value = m_value.substring(pos + 1);
442: SortedMap map = (SortedMap) m_baseCollection;
443: if (map.containsKey(key)) {
444: Object val = map.get(key);
445: CmsWidgetException error = new CmsWidgetException(
446: Messages
447: .get()
448: .container(
449: Messages.ERR_MAP_DUPLICATE_KEY_3,
450: dialog
451: .keyDefault(
452: A_CmsWidget
453: .getLabelKey(this ),
454: getKey()),
455: key, val), this );
456: setError(error);
457: throw error;
458: }
459: map.put(key, value);
460: } else {
461: CmsWidgetException error = new CmsWidgetException(
462: Messages.get().container(
463: Messages.ERR_MAP_PARAMETER_FORM_1,
464: dialog.keyDefault(A_CmsWidget
465: .getLabelKey(this ),
466: getKey())), this );
467: setError(error);
468: throw error;
469: }
470: }
471: } else if (m_baseCollection instanceof List) {
472: if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_value)) {
473: List list = (List) m_baseCollection;
474: list.add(m_value);
475: }
476: }
477: }
478:
479: /**
480: * @see org.opencms.widgets.I_CmsWidgetParameter#getDefault(org.opencms.file.CmsObject)
481: */
482: public String getDefault(CmsObject cms) {
483:
484: return m_defaultValue;
485: }
486:
487: /**
488: * Returns the name of the dialog (or dialog page) this widget parameter is used on.<p>
489: *
490: * This information can be used to create multi-page dialogs where the
491: * widgets are spread over several pages.<p>
492: *
493: * @return the name of the dialog (or dialog page) this widget parameter is used on
494: */
495: public String getDialogPage() {
496:
497: return m_dialogPage;
498: }
499:
500: /**
501: * Returns the Exception caused when this parameter value was commited, or <code>null</code>
502: * if error occured.<p>
503: *
504: * @return the Exception caused when this parameter value was commited
505: */
506: public Throwable getError() {
507:
508: return m_error;
509: }
510:
511: /**
512: * @see org.opencms.widgets.I_CmsWidgetParameter#getId()
513: */
514: public String getId() {
515:
516: return m_id;
517: }
518:
519: /**
520: * @see org.opencms.widgets.I_CmsWidgetParameter#getIndex()
521: */
522: public int getIndex() {
523:
524: return m_index;
525: }
526:
527: /**
528: * @see org.opencms.widgets.I_CmsWidgetParameter#getKey()
529: */
530: public String getKey() {
531:
532: StringBuffer result = new StringBuffer(128);
533: if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_prefix)) {
534: result.append(m_prefix);
535: result.append('.');
536: }
537: result.append(getName());
538: return result.toString();
539: }
540:
541: /**
542: * @see org.opencms.widgets.I_CmsWidgetParameter#getMaxOccurs()
543: */
544: public int getMaxOccurs() {
545:
546: return m_maxOccurs;
547: }
548:
549: /**
550: * @see org.opencms.widgets.I_CmsWidgetParameter#getMinOccurs()
551: */
552: public int getMinOccurs() {
553:
554: return m_minOccurs;
555: }
556:
557: /**
558: * @see org.opencms.widgets.I_CmsWidgetParameter#getName()
559: */
560: public String getName() {
561:
562: return m_name;
563: }
564:
565: /**
566: * @see org.opencms.widgets.I_CmsWidgetParameter#getStringValue(org.opencms.file.CmsObject)
567: */
568: public String getStringValue(CmsObject cms)
569: throws CmsRuntimeException {
570:
571: return m_value;
572: }
573:
574: /**
575: * Returns the widget for this parameter.<p>
576: *
577: * @return the widget for this parameter
578: */
579: public I_CmsWidget getWidget() {
580:
581: return m_widget;
582: }
583:
584: /**
585: * @see org.opencms.widgets.I_CmsWidgetParameter#hasError()
586: */
587: public boolean hasError() {
588:
589: return m_error != null;
590: }
591:
592: /**
593: * Checks if a value for this widget base type with the given id is available.<p>
594: *
595: * This should only be used if the base object is a collection.<p>
596: *
597: * @param index the index to check
598: *
599: * @return <code>true</code> if a value for this widget base type with the given id is available
600: */
601: public boolean hasValue(int index) {
602:
603: if (m_baseCollection instanceof List) {
604: return index < ((List) m_baseCollection).size();
605: } else if (m_baseCollection instanceof SortedMap) {
606: return index < ((SortedMap) m_baseCollection).size();
607: }
608: return false;
609: }
610:
611: /**
612: * Returns <code>true</code> if this widget parameter is mapped to a Collection base object.<p>
613: *
614: * @return <code>true</code> if this widget parameter is mapped to a Collection base object
615: */
616: public boolean isCollectionBase() {
617:
618: return (m_baseCollection != null)
619: && ((m_baseCollection instanceof List) || (m_baseCollection instanceof SortedMap));
620: }
621:
622: /**
623: * Prepares this widget dialog parameter to be commited.<p>
624: *
625: * This is required if the base type is mapped to a Collection object,
626: * becasue the collection needs to be cleared before the new values are set.<p>
627: */
628: public void prepareCommit() {
629:
630: if (m_baseCollection instanceof List) {
631: List list = (List) m_baseCollection;
632: list.clear();
633: } else if (m_baseCollection instanceof SortedMap) {
634: SortedMap map = (SortedMap) m_baseCollection;
635: map.clear();
636: }
637: }
638:
639: /**
640: * Sets the error state of this widget.<p>
641: *
642: * If the argument is <code>null</code> then the state is set to "no error".<p>
643: *
644: * @param error the error state to set
645: */
646: public void setError(Throwable error) {
647:
648: m_error = error;
649: }
650:
651: /**
652: * Sets the index to the provided value.<p>
653: *
654: * @param index the new index value to set
655: */
656: public void setindex(int index) {
657:
658: m_index = index;
659: m_id = createId(m_name, m_index);
660: }
661:
662: /**
663: * @see org.opencms.widgets.I_CmsWidgetParameter#setKeyPrefix(java.lang.String)
664: */
665: public void setKeyPrefix(String prefix) {
666:
667: m_prefix = prefix;
668: }
669:
670: /**
671: * @see org.opencms.widgets.I_CmsWidgetParameter#setStringValue(org.opencms.file.CmsObject, java.lang.String)
672: */
673: public void setStringValue(CmsObject cms, String value)
674: throws CmsIllegalArgumentException {
675:
676: m_value = value;
677: }
678:
679: /**
680: * Initializes a widget parameter with the given values.<p>
681: *
682: * @param value the initial value of the parameter
683: * @param defaultValue the default value of the parameter
684: * @param name the id of the parameter
685: * @param widget the widget used for this parameter
686: * @param dialog the dialog this parameter is used on
687: * @param minOccurs the required minimum numer of occurences of this parameter
688: * @param maxOccurs the maximum allowed numer of occurences of this parameter
689: * @param index the index of this parameter in the list
690: */
691: protected void init(String value, String defaultValue, String name,
692: I_CmsWidget widget, String dialog, int minOccurs,
693: int maxOccurs, int index) {
694:
695: if (defaultValue == null) {
696: m_defaultValue = "";
697: } else {
698: m_defaultValue = defaultValue;
699: }
700: if (value == null) {
701: m_value = m_defaultValue;
702: } else {
703: m_value = value;
704: }
705: m_name = name;
706: m_widget = widget;
707: if (maxOccurs < MAX_OCCURENCES) {
708: m_maxOccurs = maxOccurs;
709: } else {
710: m_maxOccurs = MAX_OCCURENCES;
711: }
712: if (minOccurs >= 0) {
713: m_minOccurs = minOccurs;
714: } else {
715: m_minOccurs = 0;
716: }
717: if (m_minOccurs > m_maxOccurs) {
718: m_minOccurs = m_maxOccurs;
719: }
720: m_dialogPage = dialog;
721: m_error = null;
722:
723: setindex(index);
724: }
725: }
|