001/*
002 *  Copyright 2017 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.core.ui.widgets.richtext;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.Collections;
021import java.util.HashMap;
022import java.util.HashSet;
023import java.util.List;
024import java.util.Map;
025import java.util.Set;
026
027import org.apache.avalon.framework.configuration.Configurable;
028import org.apache.avalon.framework.configuration.Configuration;
029import org.apache.avalon.framework.configuration.ConfigurationException;
030import org.apache.commons.lang3.StringUtils;
031import org.slf4j.Logger;
032
033import org.ametys.core.ui.ClientSideElement;
034import org.ametys.core.ui.ClientSideElement.ScriptFile;
035import org.ametys.plugins.core.ui.util.ConfigurationHelper;
036import org.ametys.runtime.i18n.I18nizableText;
037import org.ametys.runtime.plugin.component.AbstractLogEnabled;
038import org.ametys.runtime.plugin.component.PluginAware;
039
040/**
041 * A configurable implementation of {@link RichTextConfiguration} 
042 * 
043 * <tags category="cat1">
044 *      <tag name="p" empty="CLOSE|OPEN|REMOVE_EMPTY_CONTENT|PADDING|REMOVE_EMPTY_ATTRIBUTES">
045 *          <synonyms>
046 *              <synonym>div</synonym>
047 *          </synonyms>
048 *          <attributes>
049 *              <attribute name="align">
050 *                  <default-value>left</default-value>
051 *                  <values>
052 *                      <value>left</value>
053 *                      <value>right</value>
054 *                  </values>
055 *              </attribute>
056 *              <!-- 'class' is a special attributes with additional possibilities (technical-values) -->
057 *              <attribute name="class">
058 *                  <default-value>para1</default-value>
059 *                  <values>
060 *                      <value>para1</value>
061 *                      <value technical="true">para2</value>
062 *                  </values>
063 *              </attribute>
064 *          </attributes>    
065 *      </tag>
066 * </tags>
067 * <tags category="">
068 *    ...
069 * </tags>
070 * <styles category="">
071 *     <style name="paragraph">
072 *         <group>
073 *             <values>
074 *                 <value rendering="h1.bigger">
075 *                     <label i18n="false">Header 1 (bigger)</label>
076 *                     <description i18n="false">Creates a bigger header of first level</description>
077 *                     <cssclass>bigger-heading-1</cssclass> <!-- class name for backoffice button -->
078 *                     <icon-small type='file'>img/h1bigger_16.png</icon-small>
079 *                     <icon-medium type='file'>img/h1bigger_32.png</icon-medium>
080 *                     <icon-large type='file'>img/h1bigger_48.png</icon-large>
081 *                 </tagname>
082 *             </values>
083 *         </group>
084 *     </style>
085 * </styles>
086 * <css category="">
087 *     <file>css/file.css</file>
088 * </css>
089 * <validators category="">
090 *     <validator>
091 *         <class name="...">
092 *             <config>...</config>
093 *         </class>
094 *         <scripts>
095 *             <file>...>/file>
096 *         </scripts>
097 *     </validator>
098 * </validators>
099 * <validators category="">
100 *     ...
101 * </validators>
102 * <convertors category="">
103 *    <convertor>
104 *         <class name="...">
105 *             <config>...</config>
106 *         </class>
107 *         <scripts>
108 *             <file>...>/file>
109 *         </scripts>
110 *     </convertor>
111 * </convertors>
112 * <convertors category="">
113 *     ...
114 * </convertors>
115 */
116public class StaticRichTextConfiguration extends AbstractLogEnabled implements RichTextConfiguration, Configurable, PluginAware
117{
118    /** The name of the plugin where thie extension was defined */ 
119    protected String _pluginName;
120    /** The feature in the plugin where thie extension was defined */ 
121    protected String _featureName;
122    /** The identifier of this extension */ 
123    protected String _id;
124    
125    /** The handled tags classified by categories */
126    protected Map<String, Map<String, RichTextConfigurationTag>> _handledTags;
127    /** The css files to load by categories */
128    protected Map<String, List<ScriptFile>> _cssFiles;
129    /** The validators by categories */
130    protected Map<String, Set<ClientSideElement>> _validators;
131    /** The convertors by categories */
132    protected Map<String, Set<ClientSideElement>> _convertors;
133    /** The styles by categories */
134    protected Map<String, Map<String, Map<RichTextConfigurationStyleGroup, List<RichTextConfigurationStyle>>>> _styles;
135    
136    public void configure(Configuration configuration) throws ConfigurationException
137    {
138        _handledTags = new HashMap<>();
139        for (Configuration tagsConfiguration : configuration.getChildren("tags"))
140        {
141            String category = tagsConfiguration.getAttribute("category", "");
142            if (_handledTags.containsKey(category))
143            {
144                throw new ConfigurationException("The tag category " + (StringUtils.isNotBlank(category) ? "'" + category + "'" : "<default>") + " has been defined twice", tagsConfiguration);
145            }
146            
147            _handledTags.put(category, _configureTags(tagsConfiguration));
148        }
149        
150        _cssFiles = new HashMap<>();
151        for (Configuration cssConfiguration : configuration.getChildren("css"))
152        {
153            String category = cssConfiguration.getAttribute("category", "");
154            if (_cssFiles.containsKey(category))
155            {
156                throw new ConfigurationException("The css category " + (StringUtils.isNotBlank(category) ? "'" + category + "'" : "<default>") + " has been defined twice", cssConfiguration);
157            }
158        
159            _cssFiles.put(category, ConfigurationHelper.parsePluginResourceList(cssConfiguration, _pluginName, getLogger()));
160        }
161        
162        _validators = new HashMap<>();
163        for (Configuration validatorsConfiguration : configuration.getChildren("validators"))
164        {
165            String category = validatorsConfiguration.getAttribute("category", "");
166            if (_validators.containsKey(category))
167            {
168                throw new ConfigurationException("The validators category " + (StringUtils.isNotBlank(category) ? "'" + category + "'" : "<default>") + " has been defined twice", validatorsConfiguration);
169            }
170        
171            _validators.put(category, _configureValidators(validatorsConfiguration));
172        }
173
174        _convertors = new HashMap<>();
175        for (Configuration convertorsConfiguration : configuration.getChildren("convertors"))
176        {
177            String category = convertorsConfiguration.getAttribute("category", "");
178            if (_convertors.containsKey(category))
179            {
180                throw new ConfigurationException("The convertors category " + (StringUtils.isNotBlank(category) ? "'" + category + "'" : "<default>") + " has been defined twice", convertorsConfiguration);
181            }
182        
183            _convertors.put(category, _configureConvertors(convertorsConfiguration));
184        }
185        
186        _styles = _configureCategoryAndStyles(configuration);
187    }
188
189    public void setPluginInfo(String pluginName, String featureName, String id)
190    {
191        _pluginName = pluginName;
192        _featureName = featureName;
193        _id = id;
194    }
195    
196    /**
197     * Configure the tags
198     * @param tagsConfiguration The tags part of the configuration
199     * @return The configured tags
200     * @throws ConfigurationException If an error occurred
201     */
202    protected Map<String, RichTextConfigurationTag> _configureTags(Configuration tagsConfiguration) throws ConfigurationException
203    {
204        Map<String, RichTextConfigurationTag> tags = new HashMap<>();
205        
206        for (Configuration tagConfiguration : tagsConfiguration.getChildren("tag"))
207        {
208            RichTextConfigurationTag tag = new StaticRichTextConfigurationTag(tagConfiguration);
209            
210            if (tags.containsKey(tag.getTag()))
211            {
212                throw new ConfigurationException("The tag '" + tag.getTag() + "' cannot be defined twice in the same category", tagsConfiguration);
213            }
214            
215            tags.put(tag.getTag(), tag);
216        }
217        
218        return tags;
219    }
220
221    /**
222     * Configure the validators
223     * @param validatorsConfiguration The validators part of the configuration
224     * @return The configured validators
225     * @throws ConfigurationException If an error occurred
226     */
227    protected Set<ClientSideElement> _configureValidators(Configuration validatorsConfiguration) throws ConfigurationException
228    {
229        Set<ClientSideElement> validators = new HashSet<>();
230        
231        for (Configuration validatorConfiguration : validatorsConfiguration.getChildren("validator"))
232        {
233            validators.add(new StaticRichTextConfigurationClientSideElement(validatorConfiguration, _pluginName, getLogger()));
234        }
235        
236        return validators;
237    }
238    
239    /**
240     * Configure the convertors
241     * @param convertorsConfiguration The convertors part of the configuration
242     * @return The configured convertors
243     * @throws ConfigurationException If an error occurred
244     */
245    protected Set<ClientSideElement> _configureConvertors(Configuration convertorsConfiguration) throws ConfigurationException
246    {
247        Set<ClientSideElement> convertors = new HashSet<>();
248        
249        for (Configuration convertorConfiguration : convertorsConfiguration.getChildren("convertor"))
250        {
251            convertors.add(new StaticRichTextConfigurationClientSideElement(convertorConfiguration, _pluginName, getLogger()));
252        }
253        
254        return convertors;
255    }
256    
257    /**
258     * Configure all the styles for all categories
259     * @param configuration The styles configuration
260     * @return The configured styles
261     * @throws ConfigurationException If an error occurred
262     */
263    private Map<String, Map<String, Map<RichTextConfigurationStyleGroup, List<RichTextConfigurationStyle>>>> _configureCategoryAndStyles(Configuration configuration) throws ConfigurationException
264    {
265        Map<String, Map<String, Map<RichTextConfigurationStyleGroup, List<RichTextConfigurationStyle>>>> allStyles = new HashMap<>();
266        for (Configuration stylesConfiguration : configuration.getChildren("styles"))
267        {
268            String category = stylesConfiguration.getAttribute("category", "");
269            if (allStyles.containsKey(category))
270            {
271                throw new ConfigurationException("The style category " + (StringUtils.isNotBlank(category) ? "'" + category + "'" : "<default>") + " has been defined twice", stylesConfiguration);
272            }
273        
274            allStyles.put(category, _configureStyles(stylesConfiguration));
275        }
276        return allStyles;
277    }
278    
279    /**
280     * Configure the styles for one category
281     * @param stylesConfiguration The style configuration of the configuration
282     * @return The configured styles
283     * @throws ConfigurationException If an error occurred
284     */
285    protected Map<String, Map<RichTextConfigurationStyleGroup, List<RichTextConfigurationStyle>>> _configureStyles(Configuration stylesConfiguration) throws ConfigurationException
286    {
287        Map<String, Map<RichTextConfigurationStyleGroup, List<RichTextConfigurationStyle>>> oneStyles = new HashMap<>();
288        
289        for (Configuration styleConfiguration : stylesConfiguration.getChildren("style"))
290        {
291            String key = styleConfiguration.getAttribute("name");
292            Map<RichTextConfigurationStyleGroup, List<RichTextConfigurationStyle>> groups = new HashMap<>();
293            oneStyles.put(key, groups);
294            
295
296            for (Configuration groupConfiguration : styleConfiguration.getChildren("group"))
297            {
298                RichTextConfigurationStyleGroup group = new StaticRichTextConfigurationStyleGroup(groupConfiguration, _pluginName);
299                
300                List<RichTextConfigurationStyle> values = new ArrayList<>();
301                groups.put(group, values);
302                
303                for (Configuration valueConfiguration : groupConfiguration.getChild("values").getChildren("value"))
304                {
305                    values.add(new StaticRichTextConfigurationStyle(valueConfiguration, !"paragraph".equals(key), _pluginName, getLogger()));
306                }
307            }
308        }
309        
310        return oneStyles;
311    }
312    
313    public Set<String> getCategories()
314    {
315        Set<String> categories = new HashSet<>();
316        categories.addAll(_handledTags.keySet());
317        categories.addAll(_cssFiles.keySet());
318        categories.addAll(_validators.keySet());
319        categories.addAll(_convertors.keySet());
320        return categories;
321    }
322
323    public Collection<RichTextConfigurationTag> getHandledTags(String category, Map<String, Object> contextParameters)
324    {
325        return _handledTags.get(category).values();
326    }
327
328    public List<ScriptFile> getCSSFiles(String category, Map<String, Object> contextParameters)
329    {
330        return _cssFiles.get(category);
331    }
332
333    public Set<ClientSideElement> getValidators(String category, Map<String, Object> contextParameters)
334    {
335        return _validators.get(category);
336    }
337
338    public Set<ClientSideElement> getConvertors(String category, Map<String, Object> contextParameters)
339    {
340        return _convertors.get(category);
341    }
342    
343    public Map<String, Map<RichTextConfigurationStyleGroup, List<RichTextConfigurationStyle>>> getAvailableStyles(String category, Map<String, Object> contextualParameters)
344    {
345        return _styles.get(category);
346    }
347
348    /**
349     * A configured implementation of the {@link RichTextConfigurationTag}
350     */
351    public static class StaticRichTextConfigurationTag implements RichTextConfigurationTag
352    {
353        /** The handled tag name */
354        protected String _tagName;
355        /** The empty behavior */
356        protected EMPTY_TAG _emptyTag;
357        /** The synonyms */
358        protected Set<String> _synonyms;
359        /** The handled attributes */
360        protected Set<RichTextConfigurationAttribute> _attributes;
361        
362        /**
363         * Create by values
364         * @param tagName The tag name. Cannot be null.
365         * @param emptyTag The behavior when empty. Can be null to use CLOSE
366         * @param synonyms A set of synonyms
367         * @param attributes A set of authorized attributes
368         */
369        public StaticRichTextConfigurationTag(String tagName, EMPTY_TAG emptyTag, Set<String> synonyms, Set<RichTextConfigurationAttribute> attributes)
370        {
371            _tagName = tagName;
372            _emptyTag = emptyTag != null ? emptyTag : EMPTY_TAG.CLOSE;
373            _synonyms = synonyms != null ? synonyms : Collections.EMPTY_SET;
374            _attributes = attributes != null ? attributes : Collections.EMPTY_SET;
375        }
376        
377        /**
378         * Create by configuration
379         * @param configuration The tag configuration
380         * @throws ConfigurationException If an error occurred
381         */
382        protected StaticRichTextConfigurationTag(Configuration configuration) throws ConfigurationException
383        {
384            _tagName = configuration.getAttribute("name");
385            
386            try
387            {
388                _emptyTag = EMPTY_TAG.valueOf(configuration.getAttribute("empty", "CLOSE"));
389            }
390            catch (IllegalArgumentException e)
391            {
392                throw new ConfigurationException("The attribute empty does not accept the value '" + configuration.getAttribute("empty", "CLOSE") + "'. Should be one of <" + StringUtils.join(EMPTY_TAG.values(), "|") + ">", configuration, e);
393            }
394            
395            _synonyms = new HashSet<>();
396            for (Configuration synonymConfiguration : configuration.getChild("synonyms").getChildren("synonym"))
397            {
398                _synonyms.add(synonymConfiguration.getValue());
399            }
400            
401            _attributes = new HashSet<>();
402            for (Configuration attributeConfiguration : configuration.getChild("attributes").getChildren("attribute"))
403            {
404                RichTextConfigurationAttribute attribute = new StaticRichTextConfigurationAttribute(attributeConfiguration);
405                _attributes.add(attribute);
406            }
407        }
408
409        public String getTag()
410        {
411            return _tagName;
412        }
413
414        public EMPTY_TAG onEmptyTag()
415        {
416            return _emptyTag;
417        }
418
419        public Set<String> getSynonyms()
420        {
421            return _synonyms;
422        }
423
424        public Set<RichTextConfigurationAttribute> getAttributes()
425        {
426            return _attributes;
427        }
428    }
429    
430    /**
431     * A configured implementation of the {@link StaticRichTextConfigurationAttribute}
432     */
433    public static class StaticRichTextConfigurationAttribute implements RichTextConfigurationAttribute
434    {
435        /** The name of the attribute */
436        protected String _name;
437        /** The default value */
438        protected String _defaultValue;
439        /** The possible values */
440        protected Set<String> _authorizedValues;
441        /** The technical values */
442        protected Set<String> _technicalValues;
443
444        /**
445         * Create by values
446         * @param name The attribute name. Cannot be null.
447         * @param defaultValue The default value. Can be null
448         * @param authorizedValues A non-null set of authorized values. Must contains the default value.
449         * @param technicalValues  A non-null set of technical values. Must contains the default value.
450         */
451        public StaticRichTextConfigurationAttribute(String name, String defaultValue, Set<String> authorizedValues, Set<String> technicalValues)
452        {
453            _name = name;
454            _defaultValue = defaultValue;
455            _authorizedValues = authorizedValues != null ? authorizedValues : Collections.EMPTY_SET;
456            _technicalValues = technicalValues != null ? technicalValues : Collections.EMPTY_SET;
457        }
458        
459        /**
460         * Create by configuration
461         * @param configuration The tag configuration
462         * @throws ConfigurationException If an error occurred
463         */
464        protected StaticRichTextConfigurationAttribute(Configuration configuration) throws ConfigurationException
465        {
466            _name = configuration.getAttribute("name");
467            
468            _defaultValue = configuration.getChild("default-value").getValue(null);
469            
470            _authorizedValues = new HashSet<>();
471            _technicalValues = new HashSet<>();
472            if (_defaultValue != null)
473            {
474                _authorizedValues.add(_defaultValue);
475            }
476            for (Configuration valueConfiguration : configuration.getChild("values").getChildren("value"))
477            {
478                if ("true".equals(valueConfiguration.getAttribute("technical", "false")))
479                {
480                    _technicalValues.add(valueConfiguration.getValue());
481                }
482                _authorizedValues.add(valueConfiguration.getValue());
483            }
484        }
485        
486        public String getName()
487        {
488            return _name;
489        }
490        
491        public String getDefaultValue()
492        {
493            return _defaultValue;
494        }
495
496        public Set<String> getAuthorizedValues()
497        {
498            return _authorizedValues;
499        }
500        
501        public Set<String> getTechnicalValues()
502        {
503            return _technicalValues;
504        }
505    }
506
507    /**
508     * A configured implementation of the {@link ClientSideElement}
509     */
510    protected static class StaticRichTextConfigurationClientSideElement implements ClientSideElement
511    {
512        /** The identifier */
513        protected String _id;
514        /** The plugin name */
515        protected String _pluginName;
516        /** The script */
517        protected Script _script;
518        
519        /**
520         * Create by configuration
521         * @param configuration The tag configuration
522         * @param pluginName The name of the plugin where it was declared
523         * @param logger The logger
524         * @throws ConfigurationException If an error occurred
525         */
526        protected StaticRichTextConfigurationClientSideElement(Configuration configuration, String pluginName, Logger logger) throws ConfigurationException
527        {
528            _id = org.ametys.core.util.StringUtils.generateKey();
529            _pluginName = pluginName;
530            
531            Configuration classConfiguration = configuration.getChild("class");
532            List<ScriptFile> scriptsImports = ConfigurationHelper.parsePluginResourceList(configuration.getChild("scripts"), getPluginName(), logger);
533            List<ScriptFile> cssImports = ConfigurationHelper.parsePluginResourceList(configuration.getChild("css"), getPluginName(), logger);
534            Map<String, Object> parameters = ConfigurationHelper.parsePluginParameters(configuration.getChild("class"), getPluginName(), logger);
535            
536            _script = new Script(_id, classConfiguration.getAttribute("name"), scriptsImports, cssImports, parameters);
537        }
538
539        public String getId()
540        {
541            return _id;
542        }
543
544        public List<Script> getScripts(Map<String, Object> contextParameters)
545        {
546            return getScripts(false, contextParameters);
547        }
548
549        public List<Script> getScripts(boolean ignoreRights, Map<String, Object> contextParameters)
550        {
551            return Collections.singletonList(_script);
552        }
553
554        public Map<String, String> getRights(Map<String, Object> contextParameters)
555        {
556            return Collections.EMPTY_MAP;
557        }
558
559        public String getPluginName()
560        {
561            return _pluginName;
562        }
563
564        public Map<String, List<String>> getDependencies()
565        {
566            return Collections.EMPTY_MAP;
567        }
568    }
569    
570    /**
571     * A configured implementation of {@link RichTextConfigurationStyleGroup}
572     */
573    public static class StaticRichTextConfigurationStyleGroup implements RichTextConfigurationStyleGroup
574    {
575        /** The label */
576        protected I18nizableText _label;
577        /** The priority */
578        protected int _priority;
579
580        /**
581         * Created by configuration
582         * @param configuration The group configuration
583         * @param pluginName The name of the plugin where it was declared
584         * @throws ConfigurationException If an error occurred
585         */
586        protected StaticRichTextConfigurationStyleGroup(Configuration configuration, String pluginName) throws ConfigurationException
587        {
588            Configuration labelConfiguration = configuration.getChild("label");
589            _label = I18nizableText.getI18nizableTextValue(labelConfiguration, "plugin." + pluginName, labelConfiguration.getValue());
590            _priority = configuration.getChild("priority").getValueAsInteger(0);
591        }
592        
593        /**
594         * Created by calues
595         * @param label The label
596         * @param priority The priority
597         */
598        public StaticRichTextConfigurationStyleGroup(I18nizableText label, int priority)
599        {
600            _label = label;
601            _priority = priority;
602        }
603        
604        public I18nizableText getLabel()
605        {
606            return _label;
607        }
608
609        public int getPriority()
610        {
611            return _priority;
612        }
613    }
614    
615    /**
616     * A configured implementation of {@link RichTextConfigurationStyle}
617     */
618    public static class StaticRichTextConfigurationStyle implements RichTextConfigurationStyle
619    {
620        /** The tag name */
621        protected String _tagName;
622        /** The editor css class name */
623        protected String _className;
624        
625        /** The label */
626        protected I18nizableText _label;
627        /** The description */
628        protected I18nizableText _description;
629        /** The backoffice css class */
630        protected String _buttonCSSClass;
631        /** The icon for the button in small */
632        protected String _buttonSmallIcon;
633        /** The icon for the button in small */
634        protected String _buttonMediumIcon;
635        /** The icon for the button in small */
636        protected String _buttonLargeIcon;
637        
638        /**
639         * Create by configuration
640         * @param configuration The tag configuration
641         * @param isRenderingOnlyAClass In configuration rendering attribute can be only a class or a tag with an option ".class"
642         * @param pluginName The name of the plugin where it was declared
643         * @param logger The logger
644         * @throws ConfigurationException If an error occurred
645         */
646        protected StaticRichTextConfigurationStyle(Configuration configuration, boolean isRenderingOnlyAClass, String pluginName, Logger logger) throws ConfigurationException
647        {
648            if (isRenderingOnlyAClass)
649            {
650                _className = configuration.getAttribute("rendering");
651            }
652            else
653            {
654                _tagName = configuration.getAttribute("rendering");
655                int dotPosition = _tagName.indexOf('.');
656                if (_tagName.contains("."))
657                {
658                    _className = _tagName.substring(dotPosition + 1);
659                    _tagName = _tagName.substring(0, dotPosition);
660                }
661            }
662            
663            Map<String, Object> parsePluginParameters = ConfigurationHelper.parsePluginParameters(configuration, pluginName, logger);
664            _label = (I18nizableText) parsePluginParameters.get("label");
665            _description = (I18nizableText) parsePluginParameters.get("description");
666            _buttonCSSClass = (String) parsePluginParameters.get("cssclass");
667            _buttonSmallIcon = (String) parsePluginParameters.get("icon-small");
668            _buttonMediumIcon = (String) parsePluginParameters.get("icon-medium");
669            _buttonLargeIcon = (String) parsePluginParameters.get("icon-large");
670        }
671
672        /**
673         * Creates by values
674         * @param tagNameAndClassName The rendering for inline editor such as h1.big
675         * @param label The label for the button
676         * @param description The description for the button
677         * @param buttonCSSClass The css for the button
678         * @param buttonSmallIcon The small icon for the button
679         * @param buttonMediumIcon The medium icon for the button
680         * @param buttonLargeIcon The large icon for the button
681         * @param isRenderingOnlyAClass In configuration rendering attribute can be only a class or a tag with an option ".class"
682         */
683        public StaticRichTextConfigurationStyle(String tagNameAndClassName, I18nizableText label, I18nizableText description, String buttonCSSClass, String buttonSmallIcon, String buttonMediumIcon, String buttonLargeIcon, boolean isRenderingOnlyAClass)
684        {
685            if (isRenderingOnlyAClass)
686            {
687                _className = tagNameAndClassName;
688            }
689            else
690            {
691                _tagName = tagNameAndClassName;
692                int dotPosition = _tagName.indexOf('.');
693                if (_tagName.contains("."))
694                {
695                    _className = _tagName.substring(dotPosition + 1);
696                    _tagName = _tagName.substring(0, dotPosition);
697                }
698            }
699            
700            
701            _label = label;
702            _description = description;
703            _buttonCSSClass = buttonCSSClass;
704            _buttonSmallIcon = buttonSmallIcon;
705            _buttonMediumIcon = buttonMediumIcon;
706            _buttonLargeIcon = buttonLargeIcon;
707        }
708
709        public String getTagName()
710        {
711            return _tagName;
712        }
713
714        public String getClassName()
715        {
716            return _className;
717        }
718
719        public I18nizableText getButtonLabel()
720        {
721            return _label;
722        }
723
724        public I18nizableText getButtonDescription()
725        {
726            return _description;
727        }
728
729        public String getButtonCSSClass()
730        {
731            return _buttonCSSClass;
732        }
733
734        public String getButtonSmallIcon()
735        {
736            return _buttonSmallIcon;
737        }
738
739        public String getButtonMediumIcon()
740        {
741            return _buttonMediumIcon;
742        }
743
744        public String getButtonLargeIcon()
745        {
746            return _buttonLargeIcon;
747        }
748    }
749}