KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > frontend > templateone > form > CmsSelectWidgetXmlcontentType


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src-modules/org/opencms/frontend/templateone/form/CmsSelectWidgetXmlcontentType.java,v $
3  * Date : $Date: 2006/03/27 14:52:20 $
4  * Version: $Revision: 1.2 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (C) 2002 - 2004 Alkacon Software (http://www.alkacon.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about Alkacon Software, please see the
22  * company website: http://www.alkacon.com
23  *
24  * For further information about OpenCms, please see the
25  * project website: http://www.opencms.org
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */

31
32 package org.opencms.frontend.templateone.form;
33
34 import org.opencms.file.CmsFile;
35 import org.opencms.file.CmsObject;
36 import org.opencms.file.CmsProperty;
37 import org.opencms.file.CmsPropertyDefinition;
38 import org.opencms.file.CmsRequestContext;
39 import org.opencms.file.CmsResource;
40 import org.opencms.file.CmsResourceFilter;
41 import org.opencms.i18n.CmsLocaleManager;
42 import org.opencms.loader.CmsLoaderException;
43 import org.opencms.main.CmsException;
44 import org.opencms.main.CmsIllegalArgumentException;
45 import org.opencms.main.CmsLog;
46 import org.opencms.main.OpenCms;
47 import org.opencms.util.CmsMacroResolver;
48 import org.opencms.util.CmsStringUtil;
49 import org.opencms.widgets.CmsSelectWidget;
50 import org.opencms.widgets.CmsSelectWidgetOption;
51 import org.opencms.widgets.I_CmsWidget;
52 import org.opencms.widgets.I_CmsWidgetDialog;
53 import org.opencms.widgets.I_CmsWidgetParameter;
54 import org.opencms.xml.content.CmsXmlContent;
55 import org.opencms.xml.content.CmsXmlContentFactory;
56 import org.opencms.xml.types.I_CmsXmlContentValue;
57
58 import java.util.ArrayList JavaDoc;
59 import java.util.Collections JavaDoc;
60 import java.util.Comparator JavaDoc;
61 import java.util.HashMap JavaDoc;
62 import java.util.Iterator JavaDoc;
63 import java.util.LinkedList JavaDoc;
64 import java.util.List JavaDoc;
65 import java.util.Locale JavaDoc;
66 import java.util.Map JavaDoc;
67 import java.util.SortedSet JavaDoc;
68 import java.util.TreeSet JavaDoc;
69
70 import org.apache.commons.logging.Log;
71
72 /**
73  *
74  * A select widget that recursively collects all {@link org.opencms.xml.content.CmsXmlContent}
75  * resources of a given type (name) under a given path and creates select options that contain the
76  * xmlcontents field value specified by a name (xpath) as display String and the xmlcontents path
77  * (given) as the value.
78  * <p>
79  *
80  * The configuration String has to be of the following form: <br>
81  *
82  * <pre>
83  * &quot;folder=&lt;vfspath&gt;|displayOptionMacro=&lt;macro&gt;|resourcetypeName=&lt;typename&gt;|sortMacro=&lt;macro&gt;[|propertyname=propertyvalue]*
84  * </pre>
85  *
86  * where
87  *
88  * <pre>
89  * &lt;macro&gt;
90  * </pre>
91  *
92  * is a String containing valid OpenCms macros or xpath expression in the form:
93  *
94  * <pre>
95  * &quot;You are viewing: ${property.Title} &quot;
96  * </pre>
97  *
98  * or
99  *
100  * <pre>
101  * &quot;${xpath.Firstname} ${xpath.Lastname}, Nocakla inc.&quot;
102  * </pre>
103  *
104  * in which the xpath macros will be replaced with
105  * {@link org.opencms.xml.A_CmsXmlDocument#getValue(String, Locale)}
106  *
107  * <pre>
108  * &lt;vfspath&gt;
109  * </pre>
110  *
111  * is a valid resource path to a folder in the VFS where search is started from,
112  *
113  * <pre>
114  * &lt;typename&gt;
115  * </pre>
116  *
117  * is a resource type name defined in opencms-modules.xml and
118  *
119  * <pre>
120  * [|propertyname = propertyvalue]*
121  * </pre>
122  *
123  * is a arbitrary number of properties value mappings that have to exist on the resources to show.
124  * <p>
125  *
126  *
127  * <h3>Please note</h3>
128  * <p>
129  * <ul>
130  * <li>The widget will not offer xmlcontents that are in a different locale than the current page
131  * that displays it. <br>
132  * Only if the "matching" xmlcontent has defined a language node for the locale that is set on the
133  * page for this widget and the xpath expression to display is not empty, the xmlcontent will be
134  * selectable. </li>
135  * <li>If sortMacro is missing the values will be sorted alphabetically by their resolved display
136  * option (from the displayOptionMacro).</li>
137  * </ul>
138  * </p>
139  *
140  * @author Achim Westermann
141  *
142  * @version $Revision: 1.2 $
143  *
144  * @since 6.1.3
145  *
146  */

147 public class CmsSelectWidgetXmlcontentType extends CmsSelectWidget {
148
149     /**
150      * A {@link CmsSelectWidgetOption} that is bundled with a corresponding resource that may be
151      * selected.
152      * <p>
153      *
154      * @author Achim Westermann
155      *
156      * @version $Revision: 1.2 $
157      *
158      * @since 6.1.6
159      *
160      */

161     private static final class CmsResourceSelectWidgetOption extends CmsSelectWidgetOption {
162
163         /** The resource to select. */
164         private CmsResource m_resource;
165
166         /**
167          * Creates a non-default select option with the resource to select, the resource's name as
168          * the display text and no help text.
169          * <p>
170          *
171          * @param resource The resource of this selection.
172          *
173          */

174         public CmsResourceSelectWidgetOption(CmsResource resource) {
175
176             this(resource, false);
177
178         }
179
180         /**
181          * Creates a select option with the resource to select, the resource's name as the display
182          * text and no help text that is potentially the default selection (argument isDefault).
183          * <p>
184          *
185          * @param resource The resource of this selection.
186          *
187          * @param isDefault true, if this option is the default option (preselected.
188          *
189          */

190         public CmsResourceSelectWidgetOption(CmsResource resource, boolean isDefault) {
191
192             this(resource, isDefault, resource.getName());
193
194         }
195
196         /**
197          *
198          * Creates a select option with the resource to select, the given optionText as the display
199          * text and no help text that is potentially the default selection (argument isDefault).
200          * <p>
201          *
202          * @param resource The resource of this selection.
203          *
204          * @param isDefault true, if this option is the default option (preselected.
205          *
206          * @param optionText the text to display for this option.
207          */

208         public CmsResourceSelectWidgetOption(CmsResource resource, boolean isDefault, String JavaDoc optionText) {
209
210             this(resource, isDefault, optionText, null);
211
212         }
213
214         /**
215          * Creates a select option with the resource to select, the given optionText as the display
216          * text and the given help text that is potentially the default selection (argument
217          * isDefault).
218          * <p>
219          *
220          * @param resource The resource of this selection.
221          *
222          * @param isDefault true, if this option is the default option (preselected.
223          *
224          * @param optionText the text to display for this option.
225          *
226          * @param helpText The help text to display.
227          */

228         public CmsResourceSelectWidgetOption(CmsResource resource, boolean isDefault, String JavaDoc optionText, String JavaDoc helpText) {
229
230             super(resource.getRootPath(), isDefault, optionText, helpText);
231             m_resource = resource;
232
233         }
234
235         /**
236          * Returns the resource that is selectable.
237          * <p>
238          *
239          * @return the resource that is selectable.
240          */

241         CmsResource getResource() {
242
243             return m_resource;
244         }
245
246     }
247
248     /**
249      * Compares two {@link CmsResourceSelectWidgetOption} instances by any resource related value
250      * that may be accessed via a {@link CmsMacroResolver} (except message keys).
251      * <p>
252      *
253      * @author Achim Westermann
254      *
255      * @version $Revision: 1.2 $
256      *
257      * @since 6.1.6
258      *
259      */

260     private final class CmsResourceSelectWidgetOptionComparator implements Comparator JavaDoc {
261
262         /** The {@link CmsMacroResolver} compatible macro to resolve for comparison. * */
263         private String JavaDoc m_comparatorMacro;
264
265         /** To access resource related values with the {@link CmsMacroResolver} for comparison. * */
266         private CmsObject m_macroCmsObjectInner;
267
268         /** The {@link CmsMacroResolver} to use for macro resolvation for comparison. * */
269         private CmsMacroResolver m_macroResolverInner;
270
271         /**
272          * Creates a comparator that will resolve the {@link CmsResource} related values with the
273          * given macro expression.
274          * <p>
275          *
276          * @param cms will be cloned and used for macro - resolvation.
277          *
278          * @param comparatorMacro the macro to use to find the resource related strings to compare.
279          *
280          * @throws CmsException if sth. goes wrong.
281          *
282          * @see CmsMacroResolver
283          */

284         private CmsResourceSelectWidgetOptionComparator(CmsObject cms, String JavaDoc comparatorMacro)
285         throws CmsException {
286
287             if (CmsStringUtil.isEmpty(comparatorMacro)) {
288                 m_comparatorMacro = "${opencms.filename}";
289             } else {
290                 m_comparatorMacro = comparatorMacro;
291             }
292             m_macroCmsObjectInner = OpenCms.initCmsObject(cms);
293             m_macroCmsObjectInner.getRequestContext().setSiteRoot("/");
294             m_macroResolverInner = new CmsMacroResolver();
295             m_macroResolverInner.setCmsObject(m_macroCmsObjectInner);
296         }
297
298         /**
299          * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
300          */

301         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
302
303             CmsResourceSelectWidgetOption option1 = (CmsResourceSelectWidgetOption)o1;
304             CmsResourceSelectWidgetOption option2 = (CmsResourceSelectWidgetOption)o2;
305             CmsResource resource1 = option1.getResource();
306             CmsResource resource2 = option2.getResource();
307
308             String JavaDoc sort1, sort2;
309
310             // fool the macro resolver:
311
CmsRequestContext requestContext = m_macroCmsObjectInner.getRequestContext();
312             requestContext.setUri(resource1.getRootPath());
313             // implant the resource name for macro "${opencms.filename}:
314
m_macroResolverInner.setResourceName(resource1.getName());
315             sort1 = m_macroResolverInner.resolveMacros(m_comparatorMacro);
316             requestContext.setUri(resource2.getRootPath());
317             m_macroResolverInner.setResourceName(resource2.getName());
318             sort2 = m_macroResolverInner.resolveMacros(m_comparatorMacro);
319             return sort1.compareTo(sort2);
320         }
321
322     }
323
324     /**
325      * Configuration parameter for construction of the option display value by a macro containing
326      * xpath macros for the xmlcontent.
327      */

328     public static final String JavaDoc CONFIGURATION_OPTION_DISPLAY_MACRO = "displayOptionMacro";
329
330     /**
331      * Configuration parameter for choosing the macro to sort the display options by.
332      */

333     public static final String JavaDoc CONFIGURATION_OPTION_SORT_MACRO = "sortMacro";
334
335     /** Configuration parameter to set the name of the resource types to accept. */
336     public static final String JavaDoc CONFIGURATION_RESOURCETYPENAME = "resourcetypeName";
337
338     /** Configuration parameter to set the top folder in the VFS to search for xmlcontent resources. */
339     public static final String JavaDoc CONFIGURATION_TOPFOLDER = "folder";
340
341     /** The log object for this class. */
342     private static final Log LOG = CmsLog.getLog(CmsSelectWidgetXmlcontentType.class);
343
344     /** Only used for the macro resolver to resolve macros for the collected XML contents. */
345     protected CmsObject m_macroCmsObject;
346
347     /** The macro resolver to use. */
348     protected CmsMacroResolver m_macroResolver;
349
350     /**
351      * The macro to search for the display String of the options in xmlcontent files found below the
352      * folder to search in.
353      */

354     private String JavaDoc m_displayOptionMacro;
355
356     /** A map filled with properties and their values that have to exist on values to display. */
357     private Map JavaDoc m_filterProperties;
358
359     /** The resource folder under which the xmlcontent resources will be searched. */
360     private CmsResource m_resourceFolder;
361
362     /** The type id of xmlcontent resources to use. */
363     private int m_resourceTypeID;
364
365     /**
366      * The macro that describes the {@link CmsResource} - related value to use for sorting of the
367      * select widget options.
368      */

369     private String JavaDoc m_sortMacro;
370
371     /**
372      * Creates an unconfigured widget that has to be configured by
373      * {@link org.opencms.widgets.A_CmsWidget#setConfiguration(String)} before any html output API
374      * call is triggered.
375      * <p>
376      *
377      */

378     public CmsSelectWidgetXmlcontentType() {
379
380         this("");
381     }
382
383     /**
384      * Creates an instance with the given configuration.
385      * <p>
386      *
387      * @param configuration see the class description for the format.
388      */

389     public CmsSelectWidgetXmlcontentType(String JavaDoc configuration) {
390
391         super(configuration);
392         m_filterProperties = new HashMap JavaDoc();
393
394     }
395
396     /**
397      * Returns the displayOptionXpathMacro.
398      * <p>
399      *
400      * @return the displayOptionXpathMacro
401      */

402     public String JavaDoc getDisplayOptionMacro() {
403
404         return m_displayOptionMacro;
405     }
406
407     /**
408      * Returns the resourceFolder under which xmlcontent resources will be investigated recursively.
409      * <p>
410      *
411      * @return the resourceFolder
412      */

413     public CmsResource getResourceFolder() {
414
415         return m_resourceFolder;
416     }
417
418     /**
419      * Returns the resource type id.
420      * <p>
421      *
422      * @return the resourceTypeID
423      */

424     public int getResourceTypeID() {
425
426         return m_resourceTypeID;
427     }
428
429     /**
430      * @see org.opencms.widgets.CmsSelectWidget#newInstance()
431      */

432     public I_CmsWidget newInstance() {
433
434         return new CmsSelectWidgetXmlcontentType(getConfiguration());
435     }
436
437     /**
438      * Returns the list of configured select options, parsing the configuration String if required.
439      * <p>
440      *
441      * @param cms the current users OpenCms context.
442      *
443      * @param widgetDialog the dialog of this widget.
444      *
445      * @param param the widget parameter of this dialog.
446      *
447      * @see org.opencms.widgets.A_CmsSelectWidget#parseSelectOptions(org.opencms.file.CmsObject,
448      * org.opencms.widgets.I_CmsWidgetDialog, org.opencms.widgets.I_CmsWidgetParameter)
449      *
450      * @return the list of configured select options.
451      *
452      * @throws CmsIllegalArgumentException if the "folder" property of the configuration does not
453      * denote a folder within the VFS.
454      */

455     protected List JavaDoc parseSelectOptions(CmsObject cms, I_CmsWidgetDialog widgetDialog, I_CmsWidgetParameter param)
456     throws CmsIllegalArgumentException {
457
458         if (m_macroCmsObject == null) {
459             try {
460                 m_macroCmsObject = OpenCms.initCmsObject(cms);
461                 m_macroCmsObject.getRequestContext().setSiteRoot("/");
462             } catch (CmsException e) {
463                 // should never happen
464
if (LOG.isErrorEnabled()) {
465                     LOG.error(Messages.get().getBundle().key(
466                         Messages.ERR_SELECTWIDGET_INTERNAL_CONFIGURATION_2,
467                         new Object JavaDoc[] {getClass().getName(), getConfiguration()}));
468                 }
469                 return Collections.EMPTY_LIST;
470
471             }
472         }
473         if (m_macroResolver == null) {
474             m_macroResolver = new CmsMacroResolver();
475             m_macroResolver.setCmsObject(m_macroCmsObject);
476             m_macroResolver.setKeepEmptyMacros(true);
477         }
478
479         List JavaDoc selectOptions = getSelectOptions();
480         if (selectOptions == null) {
481             String JavaDoc configuration = getConfiguration();
482             if (configuration == null) {
483                 // workaround: use the default value to parse the options
484
configuration = param.getDefault(cms);
485             }
486             try {
487                 // parse configuration to members
488
parseConfigurationInternal(configuration, cms, param);
489
490                 // build the set of sorted options
491
SortedSet JavaDoc sortOptions = new TreeSet JavaDoc(new CmsResourceSelectWidgetOptionComparator(
492                     m_macroCmsObject,
493                     m_sortMacro));
494                 CmsSelectWidgetOption option;
495                 List JavaDoc resources;
496                 // collect all subresources of resource folder
497
CmsResourceFilter filter = CmsResourceFilter.ALL.addRequireType(getResourceTypeID());
498                 CmsRequestContext context = cms.getRequestContext();
499                 String JavaDoc oldSiteroot = context.getSiteRoot();
500                 context.setSiteRoot("/");
501                 resources = cms.readResources(m_resourceFolder.getRootPath(), filter, true);
502                 context.setSiteRoot(oldSiteroot);
503                 if (resources.size() == 0) {
504                     if (LOG.isErrorEnabled()) {
505                         LOG.error(Messages.get().getBundle().key(
506                             Messages.LOG_ERR_SELECTWIDGET_NO_RESOURCES_FOUND_3,
507                             configuration,
508                             m_resourceFolder.getRootPath(),
509                             OpenCms.getResourceManager().getResourceType(getResourceTypeID()).getTypeName()));
510                     }
511                 }
512
513                 Iterator JavaDoc itResources = resources.iterator();
514                 CmsResource resource;
515
516                 String JavaDoc displayName;
517                 // inner loop vars :
518
while (itResources.hasNext()) {
519
520                     resource = (CmsResource)itResources.next();
521                     // macro resolvation within hasFilterProperty will resolve values to the current
522
// request
523
if (hasFilterProperty(resource, cms)) {
524
525                         // implant the uri to the special cms object for resolving macros from the
526
// collected xml contents:
527
m_macroCmsObject.getRequestContext().setUri(resource.getRootPath());
528                         // implant the resource for macro "${opencms.filename}"
529
m_macroResolver.setResourceName(resource.getName());
530                         // implant the messages
531
m_macroResolver.setMessages(widgetDialog.getMessages());
532                         // filter out unwanted resources - if no filter properties are defined,
533
// every
534
// resource collected here is ok:
535
displayName = m_macroResolver.resolveMacros(getDisplayOptionMacro());
536                         // deal with a bug of the macro resolver: it will return "" if it gets
537
// "${unknown.thing}":
538
if (CmsStringUtil.isEmptyOrWhitespaceOnly(displayName)) {
539                             // it was a "${xpath.field}" expression only and swallowed by macro
540
// resolver:
541
displayName = resolveXpathMacros(cms, resource, getDisplayOptionMacro());
542                         } else {
543                             // there was more than one xpath macro: allow further replacements
544
// within partly resolved macro:
545
displayName = resolveXpathMacros(cms, resource, displayName);
546                         }
547                         // final check:
548
if (CmsStringUtil.isEmpty(displayName)) {
549                             displayName = resource.getName();
550                         }
551
552                         displayName = resolveXpathMacros(cms, resource, displayName);
553
554                         if (!CmsStringUtil.isEmpty(displayName)) {
555
556                             // now everything required is there:
557
option = new CmsResourceSelectWidgetOption(resource, false, displayName);
558                             sortOptions.add(option);
559                         }
560                     }
561                 }
562                 selectOptions = new LinkedList JavaDoc(sortOptions);
563
564             } catch (Exception JavaDoc e) {
565                 if (LOG.isErrorEnabled()) {
566                     LOG.error(Messages.get().getBundle().key(
567                         Messages.ERR_SELECTWIDGET_CONFIGURATION_2,
568                         getClass(),
569                         configuration), e);
570                 }
571             }
572
573             if (selectOptions == Collections.EMPTY_LIST) {
574                 selectOptions = new ArrayList JavaDoc();
575             }
576
577             // no method to add the parsed option list....
578
// Caution: if it is decided to return a copy of the list we are doomed unless
579
// setSelectOptions is set to protected!
580
List JavaDoc pOptions = getSelectOptions();
581             if (pOptions != null) {
582                 pOptions.clear();
583             }
584             Iterator JavaDoc it = selectOptions.iterator();
585             while (it.hasNext()) {
586                 addSelectOption((CmsSelectWidgetOption)it.next());
587             }
588         }
589         return selectOptions;
590     }
591
592     private boolean hasFilterProperty(CmsResource resource, CmsObject cms) throws CmsException {
593
594         boolean result = false;
595         Iterator JavaDoc itFilterProperties;
596         Map.Entry JavaDoc entry;
597         CmsProperty property;
598         // filter out unwanted resources - if no filter properties are defined, every
599
// resource collected here is ok:
600
if (m_filterProperties.size() > 0) {
601             itFilterProperties = m_filterProperties.entrySet().iterator();
602             while (itFilterProperties.hasNext()) {
603                 entry = (Map.Entry JavaDoc)itFilterProperties.next();
604                 property = cms.readPropertyObject(resource, (String JavaDoc)entry.getKey(), true);
605                 if (property == CmsProperty.getNullProperty()) {
606                     continue;
607                 } else {
608                     // check if value is ok:
609
if (property.getValue().equals(entry.getValue())) {
610                         // Ok, resource granted:
611
result = true;
612                         break;
613
614                     } else {
615                         // Failed, try further filter properties for match:
616
}
617                 }
618             }
619         } else {
620             // don't filter if now filter props configured
621
result = true;
622         }
623
624         return result;
625     }
626
627     /**
628      * Parses the configuration and puts it to the member variables.
629      * <p>
630      *
631      * Only invoked if options were not parsed before in this instance.
632      * <p>
633      *
634      * @param configuration the configuration (with resolved macros).
635      *
636      * @param cms needed to read the resource folder to use.
637      *
638      * @param param allows to access the resource currently being rendered.
639      *
640      *
641      * @throws CmsIllegalArgumentException if the configuration is invalid.
642      *
643      */

644     private void parseConfigurationInternal(String JavaDoc configuration, CmsObject cms, I_CmsWidgetParameter param) {
645
646         // prepare for macro resolvation of property value against the resource currently
647
// rendered
648
// implant the uri to the special cms object for resolving macros from the
649
// collected xml contents:
650
CmsFile file = ((I_CmsXmlContentValue)param).getDocument().getFile();
651         m_macroCmsObject.getRequestContext().setUri(file.getRootPath());
652         List JavaDoc mappings = CmsStringUtil.splitAsList(configuration, '|');
653         Iterator JavaDoc itMappings = mappings.iterator();
654         String JavaDoc mapping;
655         String JavaDoc[] keyValue;
656         String JavaDoc key;
657         String JavaDoc value;
658         boolean displayMacroFound = false, sortMacroFound = false, folderFound = false, typeFound = false;
659         while (itMappings.hasNext()) {
660             mapping = (String JavaDoc)itMappings.next();
661             keyValue = CmsStringUtil.splitAsArray(mapping, '=');
662             if (keyValue.length != 2) {
663                 throw new CmsIllegalArgumentException(Messages.get().container(
664                     Messages.ERR_SELECTWIDGET_CONFIGURATION_KEYVALUE_LENGTH_1,
665                     mapping));
666             }
667             key = keyValue[0].trim();
668             value = keyValue[1].trim();
669
670             // implant the resource for macro "${opencms.filename}"
671
m_macroResolver.setResourceName(file.getName());
672             // check key
673
if (CONFIGURATION_OPTION_DISPLAY_MACRO.equals(key)) {
674                 if (displayMacroFound) {
675                     throw new CmsIllegalArgumentException(Messages.get().container(
676                         Messages.ERR_SELECTWIDGET_CONFIGURATION_KEY_DUPLICATE_2,
677                         key,
678                         configuration));
679                 }
680
681                 m_displayOptionMacro = value;
682                 displayMacroFound = true;
683             } else if (CONFIGURATION_OPTION_SORT_MACRO.equals(key)) {
684                 if (sortMacroFound) {
685                     throw new CmsIllegalArgumentException(Messages.get().container(
686                         Messages.ERR_SELECTWIDGET_CONFIGURATION_KEY_DUPLICATE_2,
687                         key,
688                         configuration));
689                 }
690                 m_sortMacro = value;
691                 sortMacroFound = true;
692
693             } else if (CONFIGURATION_RESOURCETYPENAME.equals(key)) {
694                 if (typeFound) {
695                     throw new CmsIllegalArgumentException(Messages.get().container(
696                         Messages.ERR_SELECTWIDGET_CONFIGURATION_KEY_DUPLICATE_2,
697                         key,
698                         configuration));
699                 }
700                 // check if resource type name is OK
701
// if setResourceType will be implemented copy here and invoke that one
702
try {
703                     m_resourceTypeID = OpenCms.getResourceManager().getResourceType(value).getTypeId();
704                 } catch (CmsLoaderException e) {
705                     throw new CmsIllegalArgumentException(org.opencms.file.Messages.get().container(
706                         org.opencms.file.Messages.ERR_UNKNOWN_RESOURCE_TYPE_1,
707                         value), e);
708                 }
709                 typeFound = true;
710
711             } else if (CONFIGURATION_TOPFOLDER.equals(key)) {
712                 if (folderFound) {
713                     throw new CmsIllegalArgumentException(Messages.get().container(
714                         Messages.ERR_SELECTWIDGET_CONFIGURATION_KEY_DUPLICATE_2,
715                         key,
716                         configuration));
717                 }
718
719                 // allow collector path to contain macros relative to the current resource:
720
value = m_macroResolver.resolveMacros(value);
721
722                 try {
723                     CmsRequestContext context = cms.getRequestContext();
724                     String JavaDoc oldSiteRoot = context.getSiteRoot();
725                     context.setSiteRoot("/");
726                     CmsResource resource = cms.readResource(value);
727                     context.setSiteRoot(oldSiteRoot);
728                     if (resource.isFile()) {
729                         throw new CmsIllegalArgumentException(Messages.get().container(
730                             Messages.ERR_SELECTWIDGET_CONFIGURATION_RESOURCE_NOFOLDER_2,
731                             value,
732                             configuration));
733                     }
734                     m_resourceFolder = resource;
735                 } catch (CmsException e) {
736                     throw new CmsIllegalArgumentException(Messages.get().container(
737                         Messages.ERR_SELECTWIDGET_CONFIGURATION_RESOURCE_INVALID_2,
738                         value,
739                         configuration), e);
740                 }
741
742                 folderFound = true;
743             } else {
744                 // a property=value definition???
745

746                 CmsPropertyDefinition propDef;
747                 try {
748                     propDef = cms.readPropertyDefinition(key);
749                 } catch (CmsException e) {
750
751                     throw new CmsIllegalArgumentException(Messages.get().container(
752                         Messages.ERR_SELECTWIDGET_CONFIGURATION_KEY_UNKNOWN_2,
753                         key,
754                         getClass().getName()), e);
755                 }
756                 if (propDef != null) {
757                     // a valid property - value combination to filter resources for:
758
// value is potentially a macro that will be compared to the current xml content
759
// resource!
760
value = m_macroResolver.resolveMacros(value);
761                     m_filterProperties.put(key, value);
762
763                 } else {
764
765                     throw new CmsIllegalArgumentException(Messages.get().container(
766                         Messages.ERR_SELECTWIDGET_CONFIGURATION_KEY_UNKNOWN_2,
767                         key,
768                         getClass().getName()));
769                 }
770             }
771         }
772
773         // final check wether all has been set
774
if (!displayMacroFound) {
775             throw new CmsIllegalArgumentException(Messages.get().container(
776                 Messages.ERR_SELECTWIDGET_CONFIGURATION_KEY_MISSING_3,
777                 CONFIGURATION_OPTION_DISPLAY_MACRO,
778                 configuration,
779                 getClass().getName()));
780         }
781         if (!folderFound) {
782             throw new CmsIllegalArgumentException(Messages.get().container(
783                 Messages.ERR_SELECTWIDGET_CONFIGURATION_KEY_MISSING_3,
784                 CONFIGURATION_TOPFOLDER,
785                 configuration,
786                 getClass().getName()));
787         }
788         if (!typeFound) {
789             throw new CmsIllegalArgumentException(Messages.get().container(
790                 Messages.ERR_SELECTWIDGET_CONFIGURATION_KEY_MISSING_3,
791                 CONFIGURATION_RESOURCETYPENAME,
792                 configuration,
793                 getClass().getName()));
794         }
795     }
796
797     /**
798      *
799      * Resolves xpath macros of the form <code>"${xpath.XPATHEXPRESSION}"</code> by the field
800      * value of the XML content denoted by the given resource.
801      * <p>
802      *
803      * File laoding and unmarshalling is only done if the given String contains xpath macros.
804      * <p>
805      *
806      * @param cms to access values in the cmsobject.
807      *
808      * @param content the resource pointing to an xmlcontent containing the macro values to resolve.
809      *
810      * @param value the unresolved macro string.
811      *
812      * @return a String with resolved xpath macros that have been read from the xmlcontent.
813      *
814      */

815     private String JavaDoc resolveXpathMacros(CmsObject cms, CmsResource resource, String JavaDoc value) throws CmsException {
816
817         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
818         int startmacro = value.indexOf("${xpath.");
819         int stopmacro = 0;
820         String JavaDoc xpath;
821         if (startmacro != -1) {
822
823             // for the option value we have to unmarshal...
824
CmsXmlContent xmlcontent = CmsXmlContentFactory.unmarshal(cms, CmsFile.upgrade(resource, cms));
825             // we read the locale node of the xmlcontent instance matching the resources
826
// locale property (or top level locale).
827
Locale JavaDoc locale = CmsLocaleManager.getLocale(cms.readPropertyObject(
828                 xmlcontent.getFile(),
829                 CmsPropertyDefinition.PROPERTY_LOCALE,
830                 true).getValue());
831
832             while (startmacro != -1) {
833                 stopmacro = value.indexOf('}');
834                 if (stopmacro == 0) {
835                     // TODO: complain about missing closing macro bracket!
836
}
837
838                 // first cut the prefix of the macro to put it to the result:
839
result.append(value.substring(0, startmacro));
840                 // now replace the macro:
841
xpath = value.substring(startmacro + 8, stopmacro);
842                 // Foreign languages will be invisible!!!
843
// List locales = content.getLocales();
844
// if (!locales.contains(locale)) {
845
// locale = (Locale)locales.get(0);
846
// }
847
try {
848                     result.append(xmlcontent.getValue(xpath, locale).getPlainText(cms));
849                 } catch (Exception JavaDoc ex) {
850                     if (LOG.isErrorEnabled()) {
851                         LOG.error(Messages.get().getBundle().key(
852                             Messages.LOG_ERR_SELECTWIDGET_XPATH_INVALID_4,
853                             new Object JavaDoc[] {
854                                 xpath,
855                                 locale.toString(),
856                                 xmlcontent.getFile().getRootPath(),
857                                 ex.getLocalizedMessage()}));
858                     }
859                 }
860                 // skip over the consumed String of value:
861
value = value.substring(stopmacro + 1);
862
863                 // take a new start for macro:
864
startmacro = value.indexOf("${xpath.");
865             }
866         }
867         // append trailing value
868
result.append(value);
869         return result.toString();
870
871     }
872
873 }
874
Popular Tags