001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.xml.content;
029
030import org.opencms.file.CmsFile;
031import org.opencms.file.CmsObject;
032import org.opencms.file.CmsProperty;
033import org.opencms.file.CmsResource;
034import org.opencms.i18n.CmsMessages;
035import org.opencms.i18n.CmsMultiMessages.I_KeyFallbackHandler;
036import org.opencms.main.CmsException;
037import org.opencms.relations.CmsRelationType;
038import org.opencms.search.fields.CmsSearchField;
039import org.opencms.util.CmsDefaultSet;
040import org.opencms.util.CmsUUID;
041import org.opencms.widgets.I_CmsComplexWidget;
042import org.opencms.widgets.I_CmsWidget;
043import org.opencms.workplace.editors.directedit.I_CmsEditHandler;
044import org.opencms.xml.CmsXmlContentDefinition;
045import org.opencms.xml.CmsXmlException;
046import org.opencms.xml.containerpage.CmsFormatterConfiguration;
047import org.opencms.xml.types.I_CmsXmlContentValue;
048import org.opencms.xml.types.I_CmsXmlSchemaType;
049
050import java.util.Arrays;
051import java.util.Collections;
052import java.util.List;
053import java.util.Locale;
054import java.util.Map;
055import java.util.Set;
056
057import javax.servlet.ServletRequest;
058
059import org.dom4j.Element;
060
061/**
062 * Handles special XML content livetime events, and also provides XML content editor rendering hints.<p>
063 *
064 * @since 6.0.0
065 */
066public interface I_CmsXmlContentHandler {
067
068    /**
069     * The available display types for element widgets.
070     */
071    public static enum DisplayType {
072    /** The two column type. */
073    column,
074
075    /** The default display type. */
076    none,
077
078    /** The single line type. */
079    singleline,
080
081    /** The default wide display type. */
082    wide
083    }
084
085    /**
086     * The available mapping types. Currently only available for searchsettings (using the "addto" attribute in the node &lt;solrfield&gt;).
087     */
088    public static enum MappingType {
089        /** Map for the content's resource. */
090        ELEMENT,
091
092        /** Map for all container pages the content is placed on. */
093        PAGE
094    }
095
096    /** Mapping name for the 'date expired' mapping. */
097    String ATTRIBUTE_DATEEXPIRED = "dateexpired";
098
099    /** Mapping name for the 'date released' mapping. */
100    String ATTRIBUTE_DATERELEASED = "datereleased";
101
102    /** List of all allowed attribute mapping names, for fast lookup. */
103    List<String> ATTRIBUTES = Collections.unmodifiableList(
104        Arrays.asList(new String[] {ATTRIBUTE_DATERELEASED, ATTRIBUTE_DATEEXPIRED}));
105
106    /** Prefix for attribute mappings. */
107    String MAPTO_ATTRIBUTE = "attribute:";
108
109    /** Prefix for permission mappings. */
110    String MAPTO_PERMISSION = "permission:";
111
112    /** Prefix for property mappings. */
113    String MAPTO_PROPERTY = "property:";
114
115    /** Prefix for property mappings. */
116    String MAPTO_PROPERTY_INDIVIDUAL = MAPTO_PROPERTY + CmsProperty.TYPE_INDIVIDUAL + ":";
117
118    /** Prefix for property list mappings. */
119    String MAPTO_PROPERTY_LIST = "propertyList:";
120
121    /** Prefix for property list mappings. */
122    String MAPTO_PROPERTY_LIST_INDIVIDUAL = MAPTO_PROPERTY_LIST + CmsProperty.TYPE_INDIVIDUAL + ":";
123
124    /** Prefix for property list mappings. */
125    String MAPTO_PROPERTY_LIST_SHARED = MAPTO_PROPERTY_LIST + CmsProperty.TYPE_SHARED + ":";
126
127    /** Prefix for property mappings. */
128    String MAPTO_PROPERTY_SHARED = MAPTO_PROPERTY + CmsProperty.TYPE_SHARED + ":";
129
130    /** Prefix for URL name mappings. */
131    String MAPTO_URLNAME = "urlName";
132
133    /**
134     * Gets the list of allowed template context names.<p>
135     *
136     * @return the list of allowed template context names
137     */
138    CmsDefaultSet<String> getAllowedTemplates();
139
140    /**
141     * Gets the complex widget for the given schema type.<p>
142     *
143     * @param value the schema type for which we want the complex widget
144     *
145     * @return the complex widget instance for the schema type
146     */
147    I_CmsComplexWidget getComplexWidget(I_CmsXmlSchemaType value);
148
149    /**
150     * Returns the configuration String value for the widget used to edit the given XML content schema type.<p>
151     *
152     * If no configuration value is available, this method must return <code>null</code>.
153     *
154     * @param type the value to get the widget configuration for
155     *
156     * @return the configuration String value for the widget used to edit the given XML content schema type
157     */
158    String getConfiguration(I_CmsXmlSchemaType type);
159
160    /**
161     * Gets the widget configuration for the given sub-path.<p>
162     *
163     * @param remainingPath a sub-path
164     * @return the widget configuration for the given sub-path
165     */
166    String getConfiguration(String remainingPath);
167
168    /**
169     * Gets the configured display type for a given path.<p>
170     *
171     * @param path the path
172     * @param defaultVal the value to return if no configured display type is found
173     *
174     * @return the configured display type (or the default value)
175     */
176    DisplayType getConfiguredDisplayType(String path, DisplayType defaultVal);
177
178    /**
179     * Returns the resource-independent CSS resources to include into the html-page head.<p>
180     *
181     * @return the CSS resources to include into the html-page head
182     */
183    Set<String> getCSSHeadIncludes();
184
185    /**
186     * Returns all the CSS resources to include into the html-page head.<p>
187     *
188     * @param cms the current CMS context
189     * @param resource the resource from which to get the head includes
190     *
191     * @throws CmsException if something goes wrong
192     *
193     * @return the CSS resources to include into the html-page head
194     */
195    Set<String> getCSSHeadIncludes(CmsObject cms, CmsResource resource) throws CmsException;
196
197    /**
198     * Returns the default String value for the given XML content schema type object in the given XML content.<p>
199     *
200     * If a schema type does not have a default value, this method must return <code>null</code>.
201     *
202     * @param cms the current users OpenCms context
203     * @param resource the content resource
204     * @param type the type to get the default for
205     * @param path the element path
206     * @param locale the currently selected locale for the value
207     *
208     * @return the default String value for the given XML content value object
209     *
210     * @see org.opencms.xml.types.I_CmsXmlSchemaType#getDefault(Locale)
211     */
212    String getDefault(CmsObject cms, CmsResource resource, I_CmsXmlSchemaType type, String path, Locale locale);
213
214    /**
215     * Returns the default String value for the given XML content schema type object in the given XML content.<p>
216     *
217     * If a schema type does not have a default value, this method must return <code>null</code>.
218     *
219     * @param cms the current users OpenCms context
220     * @param value the value to get the default for
221     * @param locale the currently selected locale for the value
222     *
223     * @return the default String value for the given XML content value object
224     *
225     * @see org.opencms.xml.types.I_CmsXmlSchemaType#getDefault(Locale)
226     */
227    String getDefault(CmsObject cms, I_CmsXmlContentValue value, Locale locale);
228
229    /**
230     * Gets the default complex widget to be used for this type.<p>
231     *
232     * @return the default complex widget for this type
233     */
234    I_CmsComplexWidget getDefaultComplexWidget();
235
236    /**
237     * Gets the default complex widget class name configured for this type.<p>
238     *
239     * @return the default complex widget class name
240     */
241    String getDefaultComplexWidgetClass();
242
243    /**
244     * Gets the default complex widget configuration string configured for this type.<p>
245     *
246     * @return the default complex widget configuration string
247     */
248    String getDefaultComplexWidgetConfiguration();
249
250    /**
251     * Returns if the widget for this type should be displayed in compact view.<p>
252     *
253     * @param type the value to check the view mode for
254     *
255     * @return the widgets display type
256     */
257    DisplayType getDisplayType(I_CmsXmlSchemaType type);
258
259    /**
260     * Returns the edit handler if configured.<p>
261     *
262     * @return the edit handler
263     */
264    I_CmsEditHandler getEditHandler();
265
266    /**
267     * Returns the editor change handlers.<p>
268     *
269     * @return the editor change handlers
270     */
271    List<I_CmsXmlContentEditorChangeHandler> getEditorChangeHandlers();
272
273    /**
274     * Returns the container page element formatter configuration for a given resource.<p>
275     *
276     * @param cms the current users OpenCms context, used for selecting the right project
277     * @param res the resource for which the formatter configuration should be retrieved
278     *
279     * @return the container page element formatter configuration for this handler
280     */
281    CmsFormatterConfiguration getFormatterConfiguration(CmsObject cms, CmsResource res);
282
283    /**
284     * Returns the resource-independent javascript resources to include into the html-page head.<p>
285     *
286     * @return the javascript resources to include into the html-page head
287     */
288    Set<String> getJSHeadIncludes();
289
290    /**
291     * Returns all the javascript resources to include into the html-page head.<p>
292     *
293     * @param cms the current CMS context
294     * @param resource the resource for which the head includes should be retrieved
295     *
296     * @return the javascript resources to include into the html-page head
297     *
298     * @throws CmsException if something goes wrong
299     */
300    Set<String> getJSHeadIncludes(CmsObject cms, CmsResource resource) throws CmsException;
301
302    /**
303     * Returns the all mappings defined for the given element xpath.<p>
304     *
305     * @param elementName the element xpath to look up the mapping for
306     *
307     * @return the mapping defined for the given element xpath
308     */
309    List<String> getMappings(String elementName);
310
311    /**
312     * Gets the message key fallback handler.<p>
313     *
314     * This is used to automatically provide fallbacks for missing message keys in the editor.<p>
315     *
316     * @return the message key fallback handler
317     */
318    I_KeyFallbackHandler getMessageKeyHandler();
319
320    /**
321     * Returns the {@link CmsMessages} that are used to resolve localized keys
322     * for the given locale in this content handler.<p>
323     *
324     * If no localized messages are configured for this content handler,
325     * this method returns <code>null</code>.<p>
326     *
327     * @param locale the locale to get the messages for
328     *
329     * @return the {@link CmsMessages} that are used to resolve localized keys
330     * for the given locale in this content handler
331     */
332    CmsMessages getMessages(Locale locale);
333
334    /**
335     * Returns the folder name that contains eventual XML content model files to use for this resource type.<p>
336     *
337     * @return the folder name containing eventual XML content master files
338     */
339    String getModelFolder();
340
341    /**
342     * Returns the nested formatters for the given resource.<p>
343     *
344     * @param cms the cms context
345     * @param res the resource
346     * @param locale the content locale
347     * @param req the request if available
348     *
349     * @return the nested formatter ids
350     */
351    List<CmsUUID> getNestedFormatters(CmsObject cms, CmsResource res, Locale locale, ServletRequest req);
352
353    /**
354    * Gets the parameter with the given name..<p>
355    *
356    * @param param the parameter name
357    * @return the parameter value
358    */
359    String getParameter(String param);
360
361    /**
362     * Returns the preview URI for the given XML content value object to be displayed in the editor.<p>
363     *
364     * If <code>null</code> is returned, no preview is possible for contents using this handler.<p>
365     *
366     * @param cms the current OpenCms user context
367     * @param content the XML content to display the preview URI for
368     * @param resourcename the name in the VFS of the resource that is currently edited
369     *
370     * @return the preview URI for the given XML content value object to be displayed in the editor
371     */
372    String getPreview(CmsObject cms, CmsXmlContent content, String resourcename);
373
374    /**
375     * Returns the relation type for the given value.<p>
376     *
377     * @param value the value to get the relation type for
378     *
379     * @return the relation type for the given value
380     *
381     * @deprecated use {@link #getRelationType(String)} with {@link I_CmsXmlContentValue#getPath()} instead
382     */
383    @Deprecated
384    CmsRelationType getRelationType(I_CmsXmlContentValue value);
385
386    /**
387     * Returns the relation type for the given path.<p>
388     *
389     * @param path the path to get the relation type for
390     *
391     * @return the relation type for the given path
392     */
393    CmsRelationType getRelationType(String path);
394
395    /**
396     * Returns the relation type for the given path.<p>
397     *
398     * @param xpath the path to get the relation type for
399     * @param defaultType the default type if none is set
400     *
401     * @return the relation type for the given path
402     */
403    CmsRelationType getRelationType(String xpath, CmsRelationType defaultType);
404
405    /**
406     * Returns all configured Search fields for this XML content.<p>
407     *
408     * @return the Search fields for this XMl content
409     */
410    Set<CmsSearchField> getSearchFields();
411
412    /**
413     * Returns all configured Search fields for this XML content that should be attached to container pages the content is placed on.<p>
414     *
415     * @return the Search fields for this XMl content
416     */
417    Set<CmsSearchField> getSearchFieldsForPage();
418
419    /**
420     * Returns the search content settings defined in the annotation node of this XML content.<p>
421     *
422     * A search setting defined within the xsd:annotaion node of an XML schema definition can look like:<p>
423     * <code>&lt;searchsetting element="Image/Align" searchContent="false"/&gt;</code><p>
424     *
425     * The returned map contains the 'element' attribute value as keys and the 'searchContent'
426     * attribute value as values.<p>
427     *
428     * @return the search field settings for this XML content schema
429     */
430    Map<String, Boolean> getSearchSettings();
431
432    /**
433     * Returns the element settings defined for the container page formatters.<p>
434     *
435     * @param cms the current CMS context
436     * @param resource the resource for which to get the setting definitions
437     *
438     * @return the element settings defined for the container page formatters
439     */
440    Map<String, CmsXmlContentProperty> getSettings(CmsObject cms, CmsResource resource);
441
442    /**
443     * Returns the elements that require a synchronization across all locales.<p>
444     *
445     * @return the element paths
446     */
447    List<String> getSynchronizations();
448
449    /**
450     * Returns the tabs to be displayed in the editor.<p>
451     *
452     * @return the tabs to be displayed in the editor
453     */
454    List<CmsXmlContentTab> getTabs();
455
456    /**
457     * Returns the "Title" mapping set for the given XML content document in the given Locale.<p>
458     *
459     * @param cms the current OpenCms user context
460     * @param document the XML content to get the title mapping for (this must be of a type that uses this handler)
461     * @param locale the locale to get the title mapping for
462     *
463     * @return the "Title" mapping set for the given XML content document in the given Locale
464     */
465    String getTitleMapping(CmsObject cms, CmsXmlContent document, Locale locale);
466
467    /**
468     * Gets the unconfigured complex widget defined for the given path.<p>
469     *
470     * @param path the value path
471     * @return the complex widget
472     */
473    I_CmsComplexWidget getUnconfiguredComplexWidget(String path);
474
475    /**
476     * Gets an unconfigured widget for a given sub-path, i.e. one without a configuration string.<p>
477     *
478     * @param path the sub-path
479     * @return the widget for the given path
480     */
481    I_CmsWidget getUnconfiguredWidget(String path);
482
483    /**
484     * Returns the editor widget that should be used for the given XML content value.<p>
485     *
486     * The handler implementations should use the "appinfo" node of the XML content definition
487     * schema to define the mappings of elements to widgets.<p>
488     *
489     * @param value the XML content value to get the widget for
490     *
491     * @return the editor widget that should be used for the given XML content value
492     *
493     * @throws CmsXmlException if something goes wrong
494     */
495    @Deprecated
496    I_CmsWidget getWidget(I_CmsXmlSchemaType value) throws CmsXmlException;
497
498    /**
499     * Returns true if the contents for this content handler have schema-based formatters which can be disabled or enabled.<p>
500     *
501     * @return true if the contents for this content handler have schema-based formatters which can be disabled or enabled
502     */
503    boolean hasModifiableFormatters();
504
505    /**
506     * Returns whether there are nested formatters configured for this content type.<p>
507     *
508     * @return <code>true</code> if there are nested formatters configured for this content type
509     */
510    boolean hasNestedFormatters();
511
512    /**
513     * Returns if there are locale synchronized elements configured.<p>
514     *
515     * @return <code>true</code> if there are locale synchronized elements configured
516     */
517    boolean hasSynchronizedElements();
518
519    /**
520     * Returns if there are visibility handlers configured for this content type.<p>
521     *
522     * @return <code>true</code> if there are visibility handlers configured for this content type
523     */
524    boolean hasVisibilityHandlers();
525
526    /**
527     * Initializes this content handler for the given XML content definition by
528     * analyzing the "appinfo" node.<p>
529     *
530     * @param appInfoElement the "appinfo" element root node to analyze
531     * @param contentDefinition the XML content definition that XML content handler belongs to
532     *
533     * @throws CmsXmlException if something goes wrong
534     */
535    void initialize(Element appInfoElement, CmsXmlContentDefinition contentDefinition) throws CmsXmlException;
536
537    /**
538     * Performs a check of the given XML document.<p>
539     *
540     * The main difference to the {@link #resolveValidation(CmsObject, I_CmsXmlContentValue, CmsXmlContentErrorHandler)}
541     * method is that this method may silently remove some values, for instance, for broken links.<p>
542     *
543     * @param cms the current OpenCms user context
544     * @param document the document to resolve the check rules for
545     */
546    void invalidateBrokenLinks(CmsObject cms, CmsXmlContent document);
547
548    /**
549     * Checks whether the Acacia editor is disabled for this type.<p>
550     *
551     * @return true if the Acacia editor is disabled
552     */
553    boolean isAcaciaEditorDisabled();
554
555    /**
556     * Returns <code>true</code> if the XML content should be indexed when it is dropped in a container page,
557     * and returns <code>false</code> if this XML content should be indexed as 'stand-alone' document.<p>
558     *
559     * This flag is intended by excluding XML contents from the search index that are not used as detail pages,
560     * but to index those extraction result when they are part of a container page.<p>
561     *
562     * In order to set this falg add an attribute <code>containerpageOnly="true"</code> to the
563     * <code>'&lt;searchsettings&gt;-node'</code> of the XSD of the resource type you want to be indexed only
564     * when it is part of a container page.<p>
565     *
566     * @return the container page only flag
567     */
568    boolean isContainerPageOnly();
569
570    /**
571     * Returns <code>true</code> in case the given value should be searchable with
572     * the integrated full text search.<p>
573     *
574     * For the full text search, the value of all elements in one locale of the XML content are combined
575     * to one big text, which is referred to as the "content" in the context of the full text search.
576     * With this option, it is possible to hide certain elements from this "content" that does not make sense
577     * to include in the full text search.<p>
578     *
579     * @param value the XML content value to check
580     *
581     * @return <code>true</code> in case the given value should be searchable
582     */
583    boolean isSearchable(I_CmsXmlContentValue value);
584
585    /**
586     * Returns if the given content field should be visible to the current user.<p>
587     *
588     * @param cms the cms context
589     * @param schemaType the content value type
590     * @param valuePath the value path
591     * @param resource the edited resource
592     * @param contentLocale the content locale
593     *
594     * @return <code>true</code> if the given content field should be visible to the current user
595     */
596    boolean isVisible(
597        CmsObject cms,
598        I_CmsXmlSchemaType schemaType,
599        String valuePath,
600        CmsResource resource,
601        Locale contentLocale);
602
603    /**
604     * Prepares the given XML content to be used after it was read from the OpenCms VFS.<p>
605     *
606     * This method is always called after any content is unmarshalled.
607     * It can be used to perform customized actions on the given XML content.<p>
608     *
609     * @param cms the current OpenCms user context
610     * @param content the XML content to be used as read from the VFS
611     *
612     * @return the prepared content to be used
613     */
614    CmsXmlContent prepareForUse(CmsObject cms, CmsXmlContent content);
615
616    /**
617     * Prepares the given XML content to be written to the OpenCms VFS.<p>
618     *
619     * This method is always called before any content gets written.
620     * It can be used to perform XML validation, pretty - printing
621     * or customized actions on the given XML content.<p>
622     *
623     * @param cms the current OpenCms user context
624     * @param content the XML content to be written
625     * @param file the resource the XML content in it's current state was unmarshalled from
626     *
627     * @return the file to write to the OpenCms VFS, this will be an updated version of the parameter file
628     *
629     * @throws CmsException in case something goes wrong
630     */
631    CmsFile prepareForWrite(CmsObject cms, CmsXmlContent content, CmsFile file) throws CmsException;
632
633    /**
634     * Resolves the value mappings of the given XML content value, according
635     * to the rules of this XML content handler.<p>
636     *
637     * @param cms the current OpenCms user context
638     * @param content the XML content to resolve the mappings for
639     * @param value the value to resolve the mappings for
640     *
641     * @throws CmsException if something goes wrong
642     */
643    void resolveMapping(CmsObject cms, CmsXmlContent content, I_CmsXmlContentValue value) throws CmsException;
644
645    /**
646     * Performs a validation of the given XML content value, and saves all errors or warnings found in
647     * the provided XML content error handler.<p>
648     *
649     * The errorHandler parameter is optional, if <code>null</code> is given a new error handler
650     * instance must be created.<p>
651     *
652     * @param cms the current OpenCms user context
653     * @param value the value to resolve the validation rules for
654     * @param errorHandler (optional) an error handler instance that contains previous error or warnings
655     *
656     * @return an error handler that contains all errors and warnings currently found
657     */
658    CmsXmlContentErrorHandler resolveValidation(
659        CmsObject cms,
660        I_CmsXmlContentValue value,
661        CmsXmlContentErrorHandler errorHandler);
662}