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