001    package org.apache.myfaces.tobago.renderkit.html;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one or more
005     * contributor license agreements.  See the NOTICE file distributed with
006     * this work for additional information regarding copyright ownership.
007     * The ASF licenses this file to You under the Apache License, Version 2.0
008     * (the "License"); you may not use this file except in compliance with
009     * the License.  You may obtain a copy of the License at
010     *
011     *      http://www.apache.org/licenses/LICENSE-2.0
012     *
013     * Unless required by applicable law or agreed to in writing, software
014     * distributed under the License is distributed on an "AS IS" BASIS,
015     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */
019    
020    import org.apache.commons.collections.set.ListOrderedSet;
021    import org.apache.commons.lang.StringUtils;
022    import org.apache.myfaces.tobago.component.Attributes;
023    import org.apache.myfaces.tobago.component.SupportsMarkup;
024    import org.apache.myfaces.tobago.context.Markup;
025    import org.apache.myfaces.tobago.context.Theme;
026    import org.apache.myfaces.tobago.internal.util.Deprecation;
027    import org.apache.myfaces.tobago.util.ComponentUtils;
028    import org.apache.myfaces.tobago.util.VariableResolverUtils;
029    import org.slf4j.Logger;
030    import org.slf4j.LoggerFactory;
031    
032    import javax.faces.component.UIComponent;
033    import javax.faces.component.UIInput;
034    import javax.faces.context.FacesContext;
035    import java.io.Serializable;
036    import java.util.Iterator;
037    import java.util.Locale;
038    import java.util.Map;
039    
040    /**
041     * @deprecated since Tobago 1.5.0. Please use {@link org.apache.myfaces.tobago.renderkit.css.Classes}.
042     */
043    @Deprecated
044    public class StyleClasses implements Serializable {
045    
046      private static final long serialVersionUID = 3738052927067803517L;
047    
048      private static final Logger LOG = LoggerFactory.getLogger(StyleClasses.class);
049    
050      public static final char SEPARATOR = '-';
051      public static final String PREFIX = "tobago" + SEPARATOR;
052      public static final String MARKUP = SEPARATOR + "markup" + SEPARATOR;
053    
054      private ListOrderedSet classes;
055    
056      public StyleClasses() {
057        classes = new ListOrderedSet();
058      }
059    
060      /**
061       * Creates a StyleClasses element and adds one entry for a sub-component with the name of the renderer.
062       * E. g.: UITreeNode + "icon" -> tobago-treeNode-icon
063       */
064      public StyleClasses(UIComponent component, String sub) {
065        this();
066        addClass(StringUtils.uncapitalize(component.getRendererType()), sub);
067      }
068    
069      private StyleClasses(StyleClasses base) {
070        this();
071        classes.addAll(base.classes);
072      }
073    
074      public static StyleClasses ensureStyleClasses(UIComponent component) {
075        Map attributes = component.getAttributes();
076        StyleClasses classes = (StyleClasses) attributes.get(Attributes.STYLE_CLASS);
077        if (classes == null) {
078          classes = new StyleClasses();
079          attributes.put(Attributes.STYLE_CLASS, classes);
080        }
081        return classes;
082      }
083    
084      public static StyleClasses ensureStyleClassesCopy(UIComponent component) {
085        return new StyleClasses(ensureStyleClasses(component));
086      }
087    
088      /**
089       * @deprecated since Tobago 1.5.0. Please use {@link org.apache.myfaces.tobago.renderkit.css.Classes}.
090       */
091      @Deprecated
092      public void addFullQualifiedClass(String clazz) {
093        classes.add(clazz);
094      }
095      /**
096       * @deprecated since Tobago 1.5.0. Please use {@link org.apache.myfaces.tobago.renderkit.css.Classes}.
097       */
098      @Deprecated
099      public void removeFullQualifiedClass(String clazz) {
100        classes.remove(clazz);
101      }
102    
103      public void addClass(String renderer, String sub) {
104        classes.add(nameOfClass(renderer, sub));
105      }
106    
107      public void removeClass(String renderer, String sub) {
108        classes.remove(nameOfClass(renderer, sub));
109      }
110    
111      public boolean isEmpty() {
112        return classes.isEmpty();
113      }
114    
115      private String nameOfClass(String renderer, String sub) {
116        StringBuilder builder = new StringBuilder(PREFIX);
117        builder.append(renderer);
118        builder.append(SEPARATOR);
119        builder.append(sub);
120        return builder.toString();
121      }
122    
123      public void addMarkupClass(String renderer, String markup) {
124        addMarkupClass(renderer, null, markup);
125      }
126    
127      public void removeMarkupClass(String renderer, String markup) {
128        removeMarkupClass(renderer, null, markup);
129      }
130    
131      public void addMarkupClass(String renderer, String sub, String markup) {
132        classes.add(nameOfMarkupClass(renderer, sub, markup));
133      }
134    
135      public void removeMarkupClass(String renderer, String sub, String markup) {
136        classes.remove(nameOfMarkupClass(renderer, sub, markup));
137      }
138    
139      private String nameOfMarkupClass(String renderer, String sub, String markup) {
140        StringBuilder builder = new StringBuilder(PREFIX);
141        builder.append(renderer);
142        if (sub != null) {
143          builder.append(SEPARATOR);
144          builder.append(sub);
145        }
146        builder.append(MARKUP);
147        builder.append(markup);
148        return builder.toString();
149      }
150    
151      public void addMarkupClass(UIComponent component, String rendererName) {
152        if (component instanceof SupportsMarkup) {
153          addMarkupClass((SupportsMarkup) component, rendererName, null);
154        }
155      }
156    
157      public void addMarkupClass(SupportsMarkup supportsMarkup, String rendererName, String sub) {
158        Markup m = supportsMarkup.getCurrentMarkup();
159        if (m != null) {
160          for (String markup : m) {
161            Theme theme = VariableResolverUtils.resolveClientProperties(FacesContext.getCurrentInstance()).getTheme();
162            if (theme.getRenderersConfig().isMarkupSupported(rendererName, markup)) {
163              addMarkupClass(rendererName, sub, markup);
164            } else if ("none".equals(markup)) {
165              Deprecation.LOG.warn("Markup 'none' is deprecated, please use a NULL pointer instead.");
166            } else {
167              LOG.warn("Unknown markup='" + markup + "'");
168            }
169          }
170        }
171      }
172    
173      public void addAspectClass(String renderer, Aspect aspect) {
174        classes.add(nameOfAspectClass(renderer, aspect));
175      }
176    
177      public void removeAspectClass(String renderer, Aspect aspect) {
178        classes.remove(nameOfAspectClass(renderer, aspect));
179      }
180    
181      private String nameOfAspectClass(String renderer, Aspect aspect) {
182        StringBuilder builder = new StringBuilder(PREFIX);
183        builder.append(renderer);
184        builder.append(aspect);
185        return builder.toString();
186      }
187    
188      public void addAspectClass(String renderer, String sub, Aspect aspect) {
189        classes.add(nameOfAspectClass(renderer, sub, aspect));
190      }
191    
192      public void removeAspectClass(String renderer, String sub, Aspect aspect) {
193        classes.remove(nameOfAspectClass(renderer, sub, aspect));
194      }
195    
196      private String nameOfAspectClass(String renderer, String sub, Aspect aspect) {
197        StringBuilder builder = new StringBuilder(PREFIX);
198        builder.append(renderer);
199        builder.append(SEPARATOR);
200        builder.append(sub);
201        builder.append(aspect);
202        return builder.toString();
203      }
204    
205      public void addClasses(StyleClasses styleClasses) {
206        for (String clazz : (Iterable<String>) styleClasses.classes) {
207          classes.add(clazz);
208        }
209      }
210    
211      public void removeClass(String clazz) {
212        classes.remove(clazz);
213      }
214    
215      public void removeTobagoClasses(String rendererName) {
216        for (Iterator i = classes.iterator(); i.hasNext();) {
217          String clazz = (String) i.next();
218          if (clazz.startsWith(PREFIX + rendererName)) {
219            i.remove();
220          }
221        }
222      }
223    
224      public void updateClassAttributeAndMarkup(UIComponent component, String rendererName) {
225        updateClassAttribute(component, rendererName);
226        addMarkupClass(component, rendererName);
227      }
228    
229      public void updateClassAttribute(UIComponent component, String rendererName) {
230        // first remove old tobago-<rendererName>-<type> classes from class-attribute
231        removeTobagoClasses(rendererName);
232    
233        addAspectClass(rendererName, Aspect.DEFAULT);
234        if (ComponentUtils.getBooleanAttribute(component, Attributes.DISABLED)) {
235          addAspectClass(rendererName, Aspect.DISABLED);
236        }
237        if (ComponentUtils.getBooleanAttribute(component, Attributes.READONLY)) {
238          addAspectClass(rendererName, Aspect.READONLY);
239        }
240        if (ComponentUtils.getBooleanAttribute(component, Attributes.INLINE)) {
241          addAspectClass(rendererName, Aspect.INLINE);
242        }
243        if (component instanceof UIInput) {
244          UIInput input = (UIInput) component;
245          if (ComponentUtils.isError(input)) {
246            addAspectClass(rendererName, Aspect.ERROR);
247          }
248          if (input.isRequired()) {
249            addAspectClass(rendererName, Aspect.REQUIRED);
250          }
251        }
252      }
253    
254      @Override
255      public String toString() {
256        if (classes.isEmpty()) {
257          return null;
258        }
259        StringBuilder buffer = new StringBuilder(16 * classes.size());
260        for (Iterator i = classes.iterator(); i.hasNext();) {
261          String clazz = (String) i.next();
262          buffer.append(clazz);
263          if (i.hasNext()) {
264            buffer.append(' ');
265          }
266        }
267        return buffer.toString();
268      }
269    
270      /**
271       * @deprecated since Tobago 1.5.0. Please use {@link org.apache.myfaces.tobago.context.Markup}.
272       */
273      @Deprecated
274      public enum Aspect {
275    
276        DEFAULT,
277        DISABLED,
278        READONLY,
279        INLINE,
280        ERROR,
281        REQUIRED;
282    
283        private String aspect;
284    
285        Aspect() {
286          aspect = name().equals("DEFAULT") ? "" : '-' + name().toLowerCase(Locale.ENGLISH);
287        }
288    
289        @Override
290        public String toString() {
291          return aspect;
292        }
293      }
294    }