001    package org.apache.myfaces.tobago.context;
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.myfaces.tobago.internal.config.RendererConfig;
021    import org.apache.myfaces.tobago.internal.config.RenderersConfig;
022    import org.apache.myfaces.tobago.internal.config.RenderersConfigImpl;
023    import org.slf4j.Logger;
024    import org.slf4j.LoggerFactory;
025    
026    import java.io.Serializable;
027    import java.util.ArrayList;
028    import java.util.Collections;
029    import java.util.List;
030    
031    public class ThemeImpl implements Theme, Serializable {
032    
033      private static final long serialVersionUID = 1L;
034    
035      private static final Logger LOG = LoggerFactory.getLogger(ThemeImpl.class);
036    
037      private String name;
038    
039      private String displayName;
040    
041      private String deprecatedName;
042    
043      private String resourcePath;
044    
045      private ThemeImpl fallback;
046    
047      private String fallbackName;
048    
049      private List<Theme> fallbackList;
050    
051      private RenderersConfigImpl renderersConfig;
052    
053      private ThemeResources productionResources;
054    
055      private ThemeResources resources;
056    
057      private String[] productionScripts;
058    
059      private String[] productionStyles;
060    
061      private String[] scripts;
062    
063      private String[] styles;
064    
065    
066      public String getName() {
067        return name;
068      }
069    
070      public void setName(String name) {
071        this.name = name;
072      }
073    
074      public String getDisplayName() {
075        return displayName;
076      }
077    
078      public void setDisplayName(String displayName) {
079        this.displayName = displayName;
080      }
081    
082      public String getDeprecatedName() {
083        return deprecatedName;
084      }
085    
086      public void setDeprecatedName(String deprecatedName) {
087        this.deprecatedName = deprecatedName;
088      }
089    
090      public String getResourcePath() {
091        return resourcePath;
092      }
093    
094      public void setResourcePath(String resourcePath) {
095        this.resourcePath = resourcePath;
096      }
097    
098      public ThemeImpl getFallback() {
099        return fallback;
100      }
101    
102      public void setFallback(ThemeImpl fallback) {
103        this.fallback = fallback;
104      }
105    
106      public String getFallbackName() {
107        return fallbackName;
108      }
109    
110      public void setFallbackName(String fallbackName) {
111        this.fallbackName = fallbackName;
112      }
113    
114      public List<Theme> getFallbackList() {
115        return fallbackList;
116      }
117    
118      public void resolveFallbacks() {
119        fallbackList = new ArrayList<Theme>();
120        ThemeImpl actual = this;
121        while (actual != null) {
122          fallbackList.add(actual);
123          actual = actual.getFallback();
124        }
125        fallbackList = Collections.unmodifiableList(fallbackList);
126        if (LOG.isDebugEnabled()) {
127          for (Theme theme : fallbackList) {
128            LOG.debug("fallbackList: {}", theme.getName());
129          }
130        }
131      }
132    
133      public void resolveRendererConfig(RenderersConfig rendererConfigFromTobagoConfig) {
134        if (renderersConfig == null) {
135          renderersConfig = new RenderersConfigImpl();
136        }
137        if (!renderersConfig.isMerged()) {
138          ThemeImpl fallback = getFallback();
139          if (fallback != null) {
140            fallback.resolveRendererConfig(rendererConfigFromTobagoConfig);
141            RenderersConfigImpl fallbackRenderersConfig = fallback.getRenderersConfigImpl();
142            if (fallbackRenderersConfig != null) {
143              renderersConfig.merge(fallbackRenderersConfig, false);
144              if (LOG.isDebugEnabled()) {
145                LOG.debug("merge markupconfig from {} for {}", fallback.getName(), getName());
146              }
147            }
148          }
149          if (rendererConfigFromTobagoConfig != null) {
150            renderersConfig.merge(rendererConfigFromTobagoConfig, true);
151          }
152          renderersConfig.setMerged(true);
153          if (LOG.isDebugEnabled()) {
154            LOG.debug("{} {}", getName(), renderersConfig);
155          }
156        }
157      }
158    
159      public void resolveResources() {
160        ThemeImpl fallback = getFallback();
161        if (fallback != null) {
162          fallback.resolveResources();
163          addResources(fallback.getProductionResources());
164          addResources(fallback.getResources());
165        }
166      }
167    
168      public String toString() {
169        StringBuilder builder = new StringBuilder();
170        builder.append("Theme: ");
171        builder.append(name);
172        if (renderersConfig != null) {
173          builder.append("\n");
174          for (RendererConfig config : renderersConfig.getRendererConfigs()) {
175            builder.append(config);
176            builder.append("\n");
177          }
178        }
179        return builder.toString();
180      }
181    
182      public void setRenderersConfig(RenderersConfigImpl renderersConfig) {
183        this.renderersConfig = renderersConfig;
184      }
185    
186      public RenderersConfig getRenderersConfig() {
187        return renderersConfig;
188      }
189    
190      RenderersConfigImpl getRenderersConfigImpl() {
191        return renderersConfig;
192      }
193    
194      public ThemeResources getResources() {
195        return resources;
196      }
197    
198      public ThemeResources getProductionResources() {
199        return productionResources;
200      }
201    
202      public void addResources(ThemeResources resources) {
203        if (resources.isProduction()) {
204          if (productionResources != null) {
205            merge(productionResources, resources);
206          } else {
207            productionResources = resources.copy();
208          }
209        } else {
210          if (this.resources != null) {
211            merge(this.resources, resources);
212          } else {
213            this.resources = resources.copy();
214          }
215        }
216      }
217    
218      public void init() {
219        if (productionResources != null) {
220          productionScripts = new String[productionResources.getScriptList().size()];
221          for (int i = 0; i< productionResources.getScriptList().size(); i++) {
222            productionScripts[i] = productionResources.getScriptList().get(i).getName();
223          }
224          productionStyles = new String[productionResources.getStyleList().size()];
225          for (int i = 0; i< productionResources.getStyleList().size(); i++) {
226            productionStyles[i] = productionResources.getStyleList().get(i).getName();
227          }
228        }
229    
230        if (resources != null) {
231          scripts = new String[resources.getScriptList().size()];
232          for (int i = 0; i< resources.getScriptList().size(); i++) {
233            scripts[i] = resources.getScriptList().get(i).getName();
234          }
235          styles = new String[resources.getStyleList().size()];
236          for (int i = 0; i< resources.getStyleList().size(); i++) {
237            styles[i] = resources.getStyleList().get(i).getName();
238          }
239        }
240    
241      }
242    
243      private void merge(ThemeResources resources, ThemeResources toAddResources) {
244        if (resources == toAddResources) {
245          return;
246        }
247        for (int i = toAddResources.getScriptList().size()-1; i >= 0; i--) {
248          ThemeScript script = toAddResources.getScriptList().get(i);
249          resources.getScriptList().remove(script);
250          resources.getScriptList().add(0, script);
251        }
252        for (int i = toAddResources.getStyleList().size()-1; i >= 0; i--) {
253          ThemeStyle style = toAddResources.getStyleList().get(i);
254          resources.getStyleList().remove(style);
255          resources.getStyleList().add(0, style);
256        }
257      }
258    
259      public String[] getScriptResources(boolean production) {
260        if (production) {
261          return productionScripts;
262        }
263        return scripts;
264      }
265    
266      public String[] getStyleResources(boolean production) {
267        if (production) {
268          return productionStyles;
269        }
270        return styles;
271      }
272    }