001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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, please see the
018 * company website: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://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.util.CmsStringUtil;
031
032import java.io.Serializable;
033
034/**
035 * Describes both VFS properties and Container Page Element settings, used by the GWT client.<p>
036 *
037 * Warning: This class is used by GWT client-side code (See GwtBase.gwt.xml for a list of
038 * classes used by GWT client-side code). If you change this class, either make sure that
039 * your changes are compatible with GWT, or write a separate client version of the class
040 * and put it into super_src.
041 *
042 * @since 8.0.0
043 */
044public class CmsXmlContentProperty implements Serializable {
045
046    /** Type constants. */
047    public enum PropType {
048
049        /** Type constant string. */
050        string,
051        /** Type constant VFS list. */
052        vfslist;
053
054        /**
055         * Checks if the given type is {@link #vfslist}.<p>
056         *
057         * @param type the type to check
058         *
059         * @return <code>true</code> if the given type is {@link #vfslist}
060         */
061        public static boolean isVfsList(String type) {
062
063            if (type == null) {
064                return false;
065            }
066            return valueOf(type.toLowerCase()) == vfslist;
067        }
068    }
069
070    /** The property visibility options. */
071    public enum Visibility {
072
073        /** Visible only on the element. */
074        element,
075
076        /** Visible in both element and list parent as an individual setting. */
077        elementAndParentIndividual,
078
079        /** Visible in both element and list parent as a shared setting. */
080        elementAndParentShared,
081
082        /** Visible only on list parent, as individual setting. */
083        parentIndividual,
084
085        /** Visible only on list parent, as shared setting. */
086        parentShared;
087
088        /**
089         * True if it should be visible on the element itself.
090         *
091         * @return true if visible on the element
092         */
093        public boolean isVisibleOnElement() {
094
095            return (this == Visibility.element)
096                || (this == elementAndParentIndividual)
097                || (this == elementAndParentShared);
098        }
099    }
100
101    /** XML node name constants. */
102    public enum XmlNode {
103
104        /** Value file list node name. */
105        FileList,
106        /** Container or property name node name. */
107        Name,
108        /** Element properties node name. */
109        Properties,
110        /** Value string node name. */
111        String,
112        /** File list URI node name. */
113        Uri,
114        /** Value node name. */
115        Value;
116    }
117
118    /** IDs separator constant. */
119    public static final String PROP_SEPARATOR = ",";
120
121    /** The serialization uid. */
122    private static final long serialVersionUID = -7718747702874213381L;
123
124    /** The property visibility. */
125    protected Visibility m_visibility;
126
127    /** Alias names, separated by pipes, possibly null. */
128    private String m_aliasName;
129
130    /** Default value. */
131    private String m_default;
132
133    /** The description. */
134    private String m_description;
135
136    /** The error message. */
137    private String m_error;
138
139    /** The include name. */
140    private String m_includeName;
141
142    /** The name of the property. */
143    private String m_name;
144
145    /** The nice name. */
146    private String m_niceName;
147
148    /** The placeholder text. */
149    private String m_placeholder;
150
151    /** The "prefer folder" option. */
152    private String m_preferFolder;
153
154    /** The validation rule regex. */
155    private String m_ruleRegex;
156
157    /** The validation rule type. */
158    private String m_ruleType;
159
160    /** The value which indicates whether the user can influence how this property is going to be inherited. */
161    private String m_selectInherit;
162
163    /** newvalue:oldvalue pairs separated by pipes. */
164    private String m_translation;
165
166    /** The property type. */
167    private String m_type;
168
169    /** The widget to use in the editor. */
170    private String m_widget;
171
172    /** The widget configuration. */
173    private String m_widgetConfiguration;
174
175    /**
176     * Public constructor.<p>
177     *
178     * @param name the property name
179     * @param type the property type (string|uri)
180     * @param widget the widget
181     * @param widgetConfiguration the widget configuration
182     * @param ruleRegex the validation rule regex
183     * @param ruleType the validation rule type
184     * @param default1 the default value
185     * @param niceName the nice-name
186     * @param description  the description
187     * @param error the error message
188     * @param preferFolder the "prefer folder" option
189     */
190    public CmsXmlContentProperty(
191        String name,
192        String type,
193        String widget,
194        String widgetConfiguration,
195        String ruleRegex,
196        String ruleType,
197        String default1,
198        String niceName,
199        String description,
200        String error,
201        String preferFolder
202
203    ) {
204
205        this(
206            name,
207            null,
208            type,
209            null, // visibility
210            widget,
211            widgetConfiguration,
212            ruleRegex,
213            ruleType,
214            default1,
215            null,
216            niceName,
217            description,
218            error,
219            preferFolder,
220            null);
221    }
222
223    /**
224     * Public constructor.<p>
225     *
226     * @param name the property name
227     * @param aliasName the alias name (can also contain multiple aliases separated by pipes)
228     * @param type the property type (string|uri)
229     * @param visibility the visibility of the property, used in the container page element context
230     * @param widget the widget
231     * @param widgetConfiguration the widget configuration
232     * @param ruleRegex the validation rule regex
233     * @param ruleType the validation rule type
234     * @param default1 the default value
235     * @param placeholder the placeholder text
236     * @param niceName the nice-name
237     * @param description  the description
238     * @param error the error message
239     * @param preferFolder the "prefer folder" option
240     * @param translation the value translation string (newval1:oldval1|newval2:oldval2|...)
241     */
242    public CmsXmlContentProperty(
243        String name,
244        String aliasName,
245        String type,
246        Visibility visibility,
247        String widget,
248        String widgetConfiguration,
249        String ruleRegex,
250        String ruleType,
251        String default1,
252        String placeholder,
253        String niceName,
254        String description,
255        String error,
256        String preferFolder,
257        String translation
258
259    ) {
260
261        super();
262        m_name = name;
263        m_type = type;
264        m_visibility = visibility;
265        m_widget = widget;
266        m_widgetConfiguration = widgetConfiguration;
267        m_ruleRegex = ruleRegex;
268        m_ruleType = ruleType;
269        m_default = default1;
270        m_niceName = niceName;
271        m_description = description;
272        m_error = error;
273        m_preferFolder = preferFolder;
274        m_placeholder = placeholder;
275        m_aliasName = CmsStringUtil.isEmptyOrWhitespaceOnly(aliasName) ? null : aliasName;
276        m_translation = CmsStringUtil.isEmptyOrWhitespaceOnly(translation) ? null : translation;
277    }
278
279    /**
280     * Serialization constructor.<p>
281     */
282    protected CmsXmlContentProperty() {
283
284        // empty
285    }
286
287    /**
288     * Gets the fist non-null value.<p>
289     *
290     * @param o1 the first value
291     * @param o2 the second value
292     *
293     * @return the first non-null value
294     */
295    private static <T> T firstNotNull(T o1, T o2) {
296
297        if (o1 != null) {
298            return o1;
299        }
300        return o2;
301    }
302
303    /**
304     * Copies this property definition.<p>
305     *
306     * @return a new copy of the current property definition
307     */
308    public CmsXmlContentProperty copy() {
309
310        return new CmsXmlContentProperty(
311            m_name,
312            m_aliasName,
313            m_type,
314            m_visibility,
315            m_widget,
316            m_widgetConfiguration,
317            m_ruleRegex,
318            m_ruleType,
319            m_default,
320            m_placeholder,
321            m_niceName,
322            m_description,
323            m_error,
324            m_preferFolder,
325            m_translation);
326    }
327
328    /**
329     * Gets the alias name (can also be a list of alias names separated by pipes).
330     *
331     * @return the alias name(s)
332     */
333    public String getAliasName() {
334
335        return m_aliasName;
336    }
337
338    /**
339     * Gets the configured visibility, without using a default value.
340     *
341     * @return the configured visibility
342     */
343    public Visibility getConfiguredVisibility() {
344
345        return m_visibility;
346    }
347
348    /**
349     * Gets the configured widget, without using a default if it is null.<p>
350     *
351     * @return the configured widget
352     */
353    public String getConfiguredWidget() {
354
355        return m_widget;
356    }
357
358    /**
359     * Returns the default.<p>
360     *
361     * @return the default
362     */
363    public String getDefault() {
364
365        return m_default;
366    }
367
368    /**
369     * Returns the description.<p>
370     *
371     * @return the description
372     */
373    public String getDescription() {
374
375        return m_description;
376    }
377
378    /**
379     * Returns the error.<p>
380     *
381     * @return the error
382     */
383    public String getError() {
384
385        return m_error;
386    }
387
388    /**
389     * Gets the include name.<p>
390     *
391     * This is only used for element settings in formatters, where defaults from setting configuration files
392     * can be imported. The returned value is used to look up the setting name to look up for such an import in the
393     * setting configuration file.
394     *
395     * @param defaultValue the value that should be returned if no include name is configured
396     * @return the include name
397     */
398    public String getIncludeName(String defaultValue) {
399
400        if (m_includeName != null) {
401            return m_includeName;
402        }
403        return defaultValue;
404    }
405
406    /**
407     * Returns the property name.<p>
408     *
409     * @return the property name
410     */
411    public String getName() {
412
413        return m_name;
414    }
415
416    /**
417     * Returns the niceName.<p>
418     *
419     * @return the niceName
420     */
421    public String getNiceName() {
422
423        return m_niceName;
424    }
425
426    /**
427     * Gets the placeholder text.
428     *
429     * @return the placeholder text
430     */
431    public String getPlaceholder() {
432
433        return m_placeholder;
434    }
435
436    /**
437     * Returns the ruleRegex.<p>
438     *
439     * @return the ruleRegex
440     */
441    public String getRuleRegex() {
442
443        return m_ruleRegex;
444    }
445
446    /**
447     * Returns the rule type.<p>
448     *
449     * @return the rule type
450     */
451    public String getRuleType() {
452
453        return m_ruleType;
454    }
455
456    /**
457     * Returns a value which indicates whether the user can control the inheritance of this property.<p>
458     *
459     * @return the "select-inherit" property
460     */
461    public String getSelectInherit() {
462
463        return m_selectInherit;
464    }
465
466    /**
467     * Gets the value translation string, which has the form newval1:oldval1|newval2:oldval2|... .
468     *
469     * @return the value translation string
470     */
471    public String getTranslationStr() {
472
473        return m_translation;
474    }
475
476    /**
477     * Returns the property type.<p>
478     *
479     * @return the property type
480     */
481    public String getType() {
482
483        return m_type;
484    }
485
486    /**
487     * Returns the visibility of the property, used in the container page element context.<p>
488     *
489     * @param defaultValue the default value to return if the visibility is not set
490     *
491     * @return the visibility of the property
492     */
493    public Visibility getVisibility(Visibility defaultValue) {
494
495        if (m_visibility == null) {
496            return defaultValue;
497        }
498        return m_visibility;
499    }
500
501    /**
502     * Returns the widget.<p>
503     *
504     * @return the widget
505     */
506    public String getWidget() {
507
508        if (m_widget == null) {
509            return "string";
510        }
511        return m_widget;
512    }
513
514    /**
515     * Returns the widgetConfiguration.<p>
516     *
517     * @return the widgetConfiguration
518     */
519    public String getWidgetConfiguration() {
520
521        return m_widgetConfiguration;
522    }
523
524    /**
525     * Returns the value of the "prefer folder" option.<p>
526     *
527     * This flag determines whether a property entered in the sitemap entry editor should be stored by default at the folder
528     * or at the default file of a sitemap entry. It only has an effect if the sitemap entry being edited doesn't already
529     * have a value for that property at either location.<p>
530     *
531     * @return the "prefer folder" flag
532     */
533    public boolean isPreferFolder() {
534
535        return (m_preferFolder == null) || Boolean.valueOf(m_preferFolder).booleanValue();
536
537    }
538
539    /**
540     * Merges this object with another one containing default values.<p>
541     *
542     * This method does not modify this object or the object passed as a parameter.
543     * The resulting object's fields will be filled with the values from the default if they're null in this object.
544     *
545     * @param defaults the object with the defaults
546     *
547     * @return the result of merging this object with the defaults
548     */
549    public CmsXmlContentProperty mergeDefaults(CmsXmlContentProperty defaults) {
550
551        return new CmsXmlContentProperty(
552            firstNotNull(m_name, defaults.m_name),
553            firstNotNull(m_aliasName, defaults.m_aliasName),
554            firstNotNull(m_type, defaults.m_type),
555            firstNotNull(m_visibility, defaults.m_visibility),
556            firstNotNull(m_widget, defaults.m_widget),
557            firstNotNull(m_widgetConfiguration, defaults.m_widgetConfiguration),
558            firstNotNull(m_ruleRegex, defaults.m_ruleRegex),
559            firstNotNull(m_ruleType, defaults.m_ruleType),
560            firstNotNull(m_default, defaults.m_default),
561            firstNotNull(m_placeholder, defaults.m_placeholder),
562            firstNotNull(m_niceName, defaults.m_niceName),
563            firstNotNull(m_description, defaults.m_description),
564            firstNotNull(m_error, defaults.m_error),
565            firstNotNull(m_preferFolder, defaults.m_preferFolder),
566            firstNotNull(m_translation, defaults.m_translation));
567    }
568
569    /**
570     * Returns a modified copy of this bean with a different widget configuration.<p>
571     *
572     * @param config the new widget configuration
573     * @return the copy with the modified widget configuration
574     */
575    public CmsXmlContentProperty withConfig(String config) {
576
577        return new CmsXmlContentProperty(
578            m_name,
579            m_aliasName,
580            m_type,
581            m_visibility,
582            m_widget,
583            config,
584            m_ruleRegex,
585            m_ruleType,
586            m_default,
587            m_placeholder,
588            m_niceName,
589            m_description,
590            m_error,
591            m_preferFolder,
592            m_translation);
593    }
594
595    /**
596     * Copies a property definition, but replaces an empty widget with a given widget.<p>
597     *
598     * @param defaultWidget the widget to use if the set widget is empty
599     *
600     * @return the copied property definition
601     */
602    public CmsXmlContentProperty withDefaultWidget(String defaultWidget) {
603
604        return new CmsXmlContentProperty(
605            m_name,
606            m_aliasName,
607            m_type,
608            m_visibility,
609            CmsStringUtil.isEmptyOrWhitespaceOnly(m_widget) ? defaultWidget : m_widget,
610            m_widgetConfiguration,
611            m_ruleRegex,
612            m_ruleType,
613            m_default,
614            m_placeholder,
615            m_niceName,
616            m_description,
617            m_error,
618            m_preferFolder,
619            m_translation);
620    }
621
622    /**
623     * Creates a copy of this object with its include name set to a specific value.<p>
624     *
625     * @param includeName the include name to use
626     *
627     * @return the copy with the include name set
628     */
629    public CmsXmlContentProperty withIncludeName(String includeName) {
630
631        CmsXmlContentProperty result = copy();
632        if (includeName != null) {
633            includeName = includeName.trim();
634        }
635        result.m_includeName = includeName;
636        return result;
637    }
638
639    /**
640     * Copies a property definition, but replaces the nice name attribute.<p>
641     *
642     * @param name the new nice name attribute
643     *
644     * @return the copied property definition
645     */
646    public CmsXmlContentProperty withName(String name) {
647
648        return new CmsXmlContentProperty(
649            name,
650            m_aliasName,
651            m_type,
652            m_visibility,
653            m_widget,
654            m_widgetConfiguration,
655            m_ruleRegex,
656            m_ruleType,
657            m_default,
658            m_placeholder,
659            m_niceName,
660            m_description,
661            m_error,
662            m_preferFolder,
663            m_translation);
664    }
665
666    /**
667     * Copies a property definition, but replaces the nice name attribute.<p>
668     *
669     * @param niceName the new nice name attribute
670     *
671     * @return the copied property definition
672     */
673    public CmsXmlContentProperty withNiceName(String niceName) {
674
675        return new CmsXmlContentProperty(
676            m_name,
677            m_aliasName,
678            m_type,
679            m_visibility,
680            m_widget,
681            m_widgetConfiguration,
682            m_ruleRegex,
683            m_ruleType,
684            m_default,
685            m_placeholder,
686            niceName,
687            m_description,
688            m_error,
689            m_preferFolder,
690            m_translation);
691    }
692
693    /**
694     * Copies the property definition, but replaces the fields related to validation.
695     *
696     * @param pattern the validation pattern
697     * @param type the validation type
698     * @param error the validation error message
699     *
700     * @return the copied property definition
701     */
702    public CmsXmlContentProperty withValidation(String pattern, String type, String error) {
703
704        return new CmsXmlContentProperty(
705            m_name,
706            m_aliasName,
707            m_type,
708            m_visibility,
709            m_widget,
710            m_widgetConfiguration,
711            pattern,
712            type,
713            m_default,
714            m_placeholder,
715            m_niceName,
716            m_description,
717            error,
718            m_preferFolder,
719            m_translation);
720    }
721
722}