001/*
002 * (C) Copyright 2006-2007 Nuxeo SAS (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 *     Nuxeo - initial API and implementation
016 *
017 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $
018 */
019
020package org.nuxeo.ecm.platform.types;
021
022import java.io.Serializable;
023import java.util.ArrayList;
024import java.util.Collections;
025import java.util.HashMap;
026import java.util.List;
027import java.util.Map;
028
029import org.nuxeo.common.xmap.annotation.XNode;
030import org.nuxeo.common.xmap.annotation.XNodeList;
031import org.nuxeo.common.xmap.annotation.XNodeMap;
032import org.nuxeo.common.xmap.annotation.XObject;
033import org.nuxeo.ecm.platform.forms.layout.api.BuiltinModes;
034
035@XObject("type")
036public class Type implements Serializable {
037
038    private static final long serialVersionUID = 1L;
039
040    public static final String[] EMPTY_ACTIONS = new String[0];
041
042    @XNode("@id")
043    protected String id;
044
045    @XNode("icon")
046    protected String icon;
047
048    @XNode("icon-expanded")
049    protected String iconExpanded;
050
051    @XNode("bigIcon")
052    protected String bigIcon;
053
054    @XNode("bigIcon-expanded")
055    protected String bigIconExpanded;
056
057    @XNode("label")
058    protected String label;
059
060    protected Type(String id) {
061        this.id = id;
062    }
063
064    public Type() {
065
066    }
067
068    protected Map<String, SubType> allowedSubTypes = new HashMap<>();
069
070    @XNodeList(value = "subtypes/type", type = ArrayList.class, componentType = SubType.class)
071    public void addSubType(List<SubType> subTypes) {
072        if (allowedSubTypes == null) {
073            allowedSubTypes = new HashMap<String, SubType>();
074        }
075
076        for (SubType currentSubType : subTypes) {
077            SubType subTypeToMerge = allowedSubTypes.get(currentSubType.name);
078            if (subTypeToMerge == null) {
079                allowedSubTypes.put(currentSubType.name, currentSubType);
080            } else {
081                List<String> currentSubTypeHidden = currentSubType.getHidden();
082                List<String> subTypeToMergeHidden = subTypeToMerge.getHidden();
083                for (String hidden : currentSubTypeHidden) {
084                    if (!subTypeToMergeHidden.contains(hidden)) {
085                        subTypeToMergeHidden.add(hidden);
086                    }
087                }
088            }
089        }
090    }
091
092    @XNodeList(value = "deniedSubtypes/type", type = String[].class, componentType = String.class)
093    protected String[] deniedSubTypes;
094
095    @XNode("default-view")
096    protected String defaultView;
097
098    @XNode("create-view")
099    protected String createView;
100
101    @XNode("edit-view")
102    protected String editView;
103
104    @XNode("description")
105    protected String description;
106
107    @XNode("category")
108    protected String category;
109
110    protected Map<String, TypeView> views;
111
112    @XNodeList(value = "actions/action", type = String[].class, componentType = String.class)
113    protected String[] actions;
114
115    @XNodeMap(value = "layouts", key = "@mode", type = HashMap.class, componentType = Layouts.class)
116    Map<String, Layouts> layouts;
117
118    @XNodeMap(value = "contentViews", key = "@category", type = HashMap.class, componentType = DocumentContentViews.class)
119    protected Map<String, DocumentContentViews> contentViews;
120
121    // for bundle update::
122    @XNode("@remove")
123    protected boolean remove = false;
124
125    public String[] getActions() {
126        return actions;
127    }
128
129    public void setActions(String[] actions) {
130        this.actions = actions;
131    }
132
133    public String getIcon() {
134        return icon;
135    }
136
137    public void setIcon(String icon) {
138        this.icon = icon;
139    }
140
141    public String getBigIcon() {
142        return bigIcon;
143    }
144
145    public void setBigIcon(String bigIcon) {
146        this.bigIcon = bigIcon;
147    }
148
149    public String getBigIconExpanded() {
150        return bigIconExpanded;
151    }
152
153    public void setBigIconExpanded(String bigIconExpanded) {
154        this.bigIconExpanded = bigIconExpanded;
155    }
156
157    public String getLabel() {
158        return label;
159    }
160
161    public void setLabel(String label) {
162        this.label = label;
163    }
164
165    public String getId() {
166        return id;
167    }
168
169    public void setId(String id) {
170        this.id = id;
171    }
172
173    public String getDescription() {
174        return description;
175    }
176
177    public void setDescription(String description) {
178        this.description = description;
179    }
180
181    public String getCategory() {
182        return category;
183    }
184
185    public void setCategory(String category) {
186        this.category = category;
187    }
188
189    /**
190     * Returns layout names given a mode.
191     */
192    public String[] getLayouts(String mode) {
193        // default to mode ANY
194        return getLayouts(mode, BuiltinModes.ANY);
195    }
196
197    public String[] getLayouts(String mode, String defaultMode) {
198        if (layouts != null) {
199            Layouts layouts = this.layouts.get(mode);
200            if (layouts == null && defaultMode != null) {
201                layouts = this.layouts.get(defaultMode);
202            }
203            if (layouts != null) {
204                return layouts.getLayouts();
205            }
206        }
207        return null;
208    }
209
210    /**
211     * Returns the layouts map
212     */
213    public Map<String, Layouts> getLayouts() {
214        return Collections.unmodifiableMap(layouts);
215    }
216
217    public void setLayouts(Map<String, Layouts> layouts) {
218        this.layouts = layouts;
219    }
220
221    public String getDefaultView() {
222        return defaultView;
223    }
224
225    public void setDefaultView(String defaultView) {
226        this.defaultView = defaultView;
227    }
228
229    public String getCreateView() {
230        return createView;
231    }
232
233    public void setCreateView(String createView) {
234        this.createView = createView;
235    }
236
237    public String getEditView() {
238        return editView;
239    }
240
241    public void setEditView(String editView) {
242        this.editView = editView;
243    }
244
245    public TypeView[] getViews() {
246        return views.values().toArray(new TypeView[views.size()]);
247    }
248
249    @XNodeList(value = "views/view", type = TypeView[].class, componentType = TypeView.class)
250    public void setViews(TypeView[] views) {
251        this.views = new HashMap<String, TypeView>();
252        for (TypeView view : views) {
253            this.views.put(view.getId(), view);
254        }
255    }
256
257    public TypeView getView(String viewId) {
258        return views.get(viewId);
259    }
260
261    public void setView(TypeView view) {
262        views.put(view.getId(), view);
263    }
264
265    public String[] getDeniedSubTypes() {
266        return deniedSubTypes;
267    }
268
269    public void setDeniedSubTypes(String[] deniedSubTypes) {
270        this.deniedSubTypes = deniedSubTypes;
271    }
272
273    public Map<String, SubType> getAllowedSubTypes() {
274        return allowedSubTypes;
275    }
276
277    public void setAllowedSubTypes(Map<String, SubType> allowedSubTypes) {
278        this.allowedSubTypes = allowedSubTypes;
279    }
280
281    public boolean getRemove() {
282        return remove;
283    }
284
285    public void setRemove(boolean remove) {
286        this.remove = remove;
287    }
288
289    @Override
290    public String toString() {
291        final StringBuilder buf = new StringBuilder();
292        buf.append(Type.class.getSimpleName());
293        buf.append(" {");
294        buf.append("id: ");
295        buf.append(id);
296        buf.append('}');
297        return buf.toString();
298    }
299
300    public String getIconExpanded() {
301        return iconExpanded;
302    }
303
304    public void setIconExpanded(String iconExpanded) {
305        this.iconExpanded = iconExpanded;
306    }
307
308    /**
309     * Return content views defined on this document type for given category
310     *
311     * @since 5.4
312     */
313    public String[] getContentViews(String category) {
314        if (contentViews != null) {
315            DocumentContentViews cv = contentViews.get(category);
316            if (cv != null) {
317                return cv.getContentViewNames();
318            }
319        }
320        return null;
321    }
322
323    public Map<String, DocumentContentViews> getContentViews() {
324        return Collections.unmodifiableMap(contentViews);
325    }
326
327    public void setContentViews(Map<String, DocumentContentViews> contentViews) {
328        this.contentViews = contentViews;
329    }
330
331    /**
332     * Clone method to handle hot reload
333     *
334     * @since 5.6
335     */
336    @Override
337    public Type clone() {
338        Type clone = new Type();
339        clone.setId(getId());
340        clone.setIcon(getIcon());
341        clone.setIconExpanded(getIconExpanded());
342        clone.setBigIcon(getBigIcon());
343        clone.setBigIconExpanded(getBigIconExpanded());
344        clone.setLabel(getLabel());
345        Map<String, SubType> subs = getAllowedSubTypes();
346        if (subs != null) {
347            Map<String, SubType> csubs = new HashMap<String, SubType>();
348            for (Map.Entry<String, SubType> item : subs.entrySet()) {
349                csubs.put(item.getKey(), item.getValue().clone());
350            }
351            clone.setAllowedSubTypes(csubs);
352        }
353        String[] denied = getDeniedSubTypes();
354        if (denied != null) {
355            clone.setDeniedSubTypes(denied.clone());
356        }
357        clone.setDefaultView(getDefaultView());
358        clone.setCreateView(getCreateView());
359        clone.setEditView(getEditView());
360        clone.setDescription(getDescription());
361        clone.setCategory(getCategory());
362        if (views != null) {
363            Map<String, TypeView> cviews = new HashMap<String, TypeView>();
364            for (Map.Entry<String, TypeView> item : views.entrySet()) {
365                cviews.put(item.getKey(), item.getValue().clone());
366            }
367            clone.views = cviews;
368        }
369        String[] actions = getActions();
370        if (actions != null) {
371            clone.setActions(actions.clone());
372        }
373        // do not clone old layout definition, nobody's using it anymore
374        Map<String, Layouts> layouts = getLayouts();
375        if (layouts != null) {
376            Map<String, Layouts> clayouts = new HashMap<String, Layouts>();
377            for (Map.Entry<String, Layouts> item : layouts.entrySet()) {
378                clayouts.put(item.getKey(), item.getValue().clone());
379            }
380            clone.setLayouts(clayouts);
381        }
382        Map<String, DocumentContentViews> cvs = getContentViews();
383        if (cvs != null) {
384            Map<String, DocumentContentViews> ccvs = new HashMap<String, DocumentContentViews>();
385            for (Map.Entry<String, DocumentContentViews> item : cvs.entrySet()) {
386                ccvs.put(item.getKey(), item.getValue().clone());
387            }
388            clone.setContentViews(ccvs);
389        }
390        clone.setRemove(getRemove());
391        return clone;
392    }
393
394}