001/*
002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     Anahide Tchertchian
018 */
019package org.nuxeo.theme.styling.service.descriptors;
020
021import java.util.ArrayList;
022import java.util.List;
023
024import org.apache.commons.lang3.builder.EqualsBuilder;
025import org.nuxeo.common.xmap.annotation.XNode;
026import org.nuxeo.common.xmap.annotation.XNodeList;
027import org.nuxeo.common.xmap.annotation.XObject;
028import org.nuxeo.ecm.web.resources.api.ResourceBundle;
029import org.nuxeo.ecm.web.resources.api.ResourceType;
030import org.nuxeo.ecm.web.resources.core.ResourceBundleDescriptor;
031
032/**
033 * Descriptor to associate resources and flavors to a page.
034 *
035 * @since 7.4
036 */
037@XObject("page")
038public class PageDescriptor {
039
040    public static final String RESOURCE_BUNDLE_PREFIX = "pageResourceBundle_";
041
042    @XNode("@name")
043    String name;
044
045    /**
046     * @since 7.4
047     */
048    @XNode("@charset")
049    String charset;
050
051    @XNode("defaultFlavor")
052    String defaultFlavor;
053
054    /**
055     * @deprecated since 7.4: use resources instead
056     */
057    @Deprecated
058    @XNode("styles@append")
059    boolean appendStyles;
060
061    /**
062     * @deprecated since 7.4: use resources instead
063     */
064    @Deprecated
065    @XNodeList(value = "styles/style", type = ArrayList.class, componentType = String.class)
066    List<String> styles;
067
068    @XNode("flavors@append")
069    boolean appendFlavors;
070
071    @XNodeList(value = "flavors/flavor", type = ArrayList.class, componentType = String.class)
072    List<String> flavors;
073
074    @XNode("resources@append")
075    boolean appendResources;
076
077    @XNodeList(value = "resources/resource", type = ArrayList.class, componentType = String.class)
078    List<String> resources;
079
080    /**
081     * @since 7.4
082     */
083    @XNodeList(value = "resources/bundle", type = ArrayList.class, componentType = String.class)
084    List<String> bundles;
085
086    public String getName() {
087        return name;
088    }
089
090    public String getDefaultFlavor() {
091        return defaultFlavor;
092    }
093
094    public void setDefaultFlavor(String defaultFlavor) {
095        this.defaultFlavor = defaultFlavor;
096    }
097
098    /**
099     * @deprecated since 7.4: use resources instead
100     */
101    public boolean getAppendStyles() {
102        return appendStyles;
103    }
104
105    /**
106     * @deprecated since 7.4: use resources instead
107     */
108    public List<String> getStyles() {
109        return styles;
110    }
111
112    public boolean getAppendFlavors() {
113        return appendFlavors;
114    }
115
116    public List<String> getFlavors() {
117        return flavors;
118    }
119
120    public void setName(String name) {
121        this.name = name;
122    }
123
124    public void setStyles(List<String> styles) {
125        this.styles = styles;
126    }
127
128    public void setFlavors(List<String> flavors) {
129        this.flavors = flavors;
130    }
131
132    public boolean getAppendResources() {
133        return appendResources;
134    }
135
136    public boolean hasResources() {
137        return !getResources().isEmpty();
138    }
139
140    public List<String> getResources() {
141        List<String> res = new ArrayList<String>();
142        // BBB
143        if (styles != null) {
144            for (String style : styles) {
145                if (style == null) {
146                    continue;
147                }
148                if (style.endsWith(ResourceType.css.name())) {
149                    res.add(style);
150                } else {
151                    res.add(style + "." + ResourceType.css.name());
152                }
153            }
154        }
155        if (resources != null) {
156            res.addAll(resources);
157        }
158        return res;
159    }
160
161    public void setResources(List<String> resources) {
162        this.resources = resources;
163    }
164
165    public String getComputedResourceBundleName() {
166        if ("*".equals(getName())) {
167            return RESOURCE_BUNDLE_PREFIX + "*";
168        }
169        return RESOURCE_BUNDLE_PREFIX + getName().replaceAll("[^a-zA-Z]+", "_");
170    }
171
172    public ResourceBundle getComputedResourceBundle() {
173        if (hasResources()) {
174            ResourceBundleDescriptor bundle = new ResourceBundleDescriptor();
175            bundle.setName(getComputedResourceBundleName());
176            bundle.setResources(getResources());
177            bundle.setAppend(getAppendResources());
178            return bundle;
179        }
180        return null;
181    }
182
183    /**
184     * @since 7.4
185     */
186    public List<String> getResourceBundles() {
187        List<String> all = new ArrayList<String>();
188        if (bundles != null) {
189            all.addAll(bundles);
190        }
191        if (hasResources()) {
192            all.add(getComputedResourceBundleName());
193        }
194        return all;
195    }
196
197    /**
198     * @since 7.4
199     */
200    public void setResourceBundles(List<String> bundles) {
201        this.bundles = bundles;
202    }
203
204    public void setAppendStyles(boolean appendStyles) {
205        this.appendStyles = appendStyles;
206    }
207
208    public void setAppendFlavors(boolean appendFlavors) {
209        this.appendFlavors = appendFlavors;
210    }
211
212    public void setAppendResources(boolean appendResources) {
213        this.appendResources = appendResources;
214    }
215
216    /**
217     * @since 7.4
218     */
219    public String getCharset() {
220        return charset;
221    }
222
223    /**
224     * @since 7.4
225     */
226    public void setCharset(String charset) {
227        this.charset = charset;
228    }
229
230    public void merge(PageDescriptor src) {
231        String newFlavor = src.getDefaultFlavor();
232        if (newFlavor != null) {
233            setDefaultFlavor(newFlavor);
234        }
235
236        String newCharset = src.getCharset();
237        if (newCharset != null) {
238            setCharset(newCharset);
239        }
240
241        List<String> newStyles = src.getStyles();
242        if (newStyles != null) {
243            List<String> merged = new ArrayList<String>();
244            merged.addAll(newStyles);
245            boolean keepOld = src.getAppendStyles() || (newStyles.isEmpty() && !src.getAppendStyles());
246            if (keepOld) {
247                // add back old contributions
248                List<String> oldStyles = getStyles();
249                if (oldStyles != null) {
250                    merged.addAll(0, oldStyles);
251                }
252            }
253            setStyles(merged);
254        }
255
256        List<String> newFlavors = src.getFlavors();
257        if (newFlavors != null) {
258            List<String> merged = new ArrayList<String>();
259            merged.addAll(newFlavors);
260            boolean keepOld = src.getAppendFlavors() || (newFlavors.isEmpty() && !src.getAppendFlavors());
261            if (keepOld) {
262                // add back old contributions
263                List<String> oldFlavors = getFlavors();
264                if (oldFlavors != null) {
265                    merged.addAll(0, oldFlavors);
266                }
267            }
268            setFlavors(merged);
269        }
270
271        List<String> newResources = src.resources;
272        if (newResources != null) {
273            List<String> merged = new ArrayList<String>();
274            merged.addAll(newResources);
275            boolean keepOld = src.getAppendResources() || (newResources.isEmpty() && !src.getAppendResources());
276            if (keepOld) {
277                // add back old contributions
278                List<String> oldResources = resources;
279                if (oldResources != null) {
280                    merged.addAll(0, oldResources);
281                }
282            }
283            setResources(merged);
284        }
285
286        List<String> newBundles = src.bundles;
287        if (newBundles != null) {
288            List<String> merged = new ArrayList<String>();
289            merged.addAll(newBundles);
290            boolean keepOld = src.getAppendResources() || (newBundles.isEmpty() && !src.getAppendResources());
291            if (keepOld) {
292                // add back old contributions
293                List<String> oldBundles = bundles;
294                if (oldBundles != null) {
295                    merged.addAll(0, oldBundles);
296                }
297            }
298            setResourceBundles(merged);
299        }
300    }
301
302    @Override
303    public PageDescriptor clone() {
304        PageDescriptor clone = new PageDescriptor();
305        clone.setName(getName());
306        clone.setCharset(getCharset());
307        clone.setDefaultFlavor(getDefaultFlavor());
308        clone.setAppendStyles(getAppendStyles());
309        List<String> styles = getStyles();
310        if (styles != null) {
311            clone.setStyles(new ArrayList<String>(styles));
312        }
313        clone.setAppendFlavors(getAppendFlavors());
314        List<String> flavors = getFlavors();
315        if (flavors != null) {
316            clone.setFlavors(new ArrayList<String>(flavors));
317        }
318        clone.setAppendResources(getAppendResources());
319        if (resources != null) {
320            clone.setResources(new ArrayList<String>(resources));
321        }
322        if (bundles != null) {
323            clone.setResourceBundles(new ArrayList<String>(bundles));
324        }
325        return clone;
326    }
327
328    @Override
329    public boolean equals(Object obj) {
330        if (!(obj instanceof PageDescriptor)) {
331            return false;
332        }
333        if (obj == this) {
334            return true;
335        }
336        PageDescriptor p = (PageDescriptor) obj;
337        return new EqualsBuilder().append(name, p.name).append(charset, p.charset).append(defaultFlavor,
338                p.defaultFlavor).append(appendStyles, p.appendStyles).append(styles, p.styles).append(appendFlavors,
339                p.appendFlavors).append(flavors, p.flavors).append(appendResources, p.appendResources).append(
340                resources, p.resources).append(bundles, p.bundles).isEquals();
341    }
342
343}