001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     bstefanescu
011 *
012 * $Id$
013 */
014
015package org.nuxeo.ecm.platform.rendering.api;
016
017import java.util.ArrayList;
018import java.util.Arrays;
019import java.util.Calendar;
020import java.util.Collection;
021import java.util.HashMap;
022import java.util.Map;
023
024import org.nuxeo.ecm.core.api.Blob;
025import org.nuxeo.ecm.core.api.Blobs;
026import org.nuxeo.ecm.core.api.CoreSession;
027import org.nuxeo.ecm.core.api.DocumentModel;
028import org.nuxeo.ecm.core.api.PropertyException;
029import org.nuxeo.ecm.core.api.model.PropertyNotFoundException;
030import org.nuxeo.ecm.core.schema.FacetNames;
031import org.nuxeo.ecm.platform.rendering.fm.adapters.SchemaTemplate;
032
033/**
034 * Base class to build views for Document oriented contexts (contexts that are bound to a document).
035 * <p>
036 * Note that this class cannot be used with contexts for which the {@link RenderingContext#getDocument()} method is
037 * returning null.
038 * <p>
039 * This implementation ensure that the context argument is never used so it can be used outside the scope of a rendering
040 * context to get a view over the document.
041 *
042 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
043 */
044public class DefaultDocumentView implements DocumentView {
045
046    // Must be returned by get() method when the key is unknown since the caller
047    // should be able to
048    // treat differently a key hit that returned null from a key that is not
049    // known by this view
050    public static final Object UNKNOWN = new Object();
051
052    public interface Field {
053        String getName();
054
055        Object getValue(DocumentModel doc);
056    }
057
058    protected final Map<String, Field> fields;
059
060    public DefaultDocumentView() {
061        fields = new HashMap<String, Field>();
062        initialize();
063    }
064
065    public DefaultDocumentView(Map<String, Field> fields) {
066        this.fields = fields == null ? new HashMap<String, Field>() : fields;
067    }
068
069    protected void initialize() {
070        addField(SESSION);
071
072        addField(ID);
073        addField(NAME);
074        addField(PATH);
075        addField(TYPE);
076        addField(SID);
077        addField(REPOSITORY);
078
079        addField(SCHEMAS);
080        addField(FACETS);
081        addField(LOCKED);
082        addField(LIFE_CYCLE_STATE);
083        addField(LIFE_CYCLE_POLICY);
084        addField(ALLOWED_STATE_TRANSITIONS);
085        addField(IS_FOLDER);
086        addField(TITLE);
087        addField(AUTHOR);
088        addField(CREATED);
089        addField(MODIFIED);
090        addField(CONTENT);
091
092        addField(PARENT);
093        addField(CHILDREN);
094        addField(REF);
095        addField(VERSIONS);
096        addField(PROXIES);
097        addField(VERSION_LABEL);
098        addField(SOURCE_ID);
099    }
100
101    public final void addField(Field field) {
102        fields.put(field.getName(), field);
103    }
104
105    public final void addFields(Collection<Field> fields) {
106        for (Field field : fields) {
107            this.fields.put(field.getName(), field);
108        }
109    }
110
111    public final void removeField(String name) {
112        fields.remove(name);
113    }
114
115    public Field getField(String name) {
116        return fields.get(name);
117    }
118
119    public Object get(DocumentModel doc, String name) throws PropertyException {
120        Field field = fields.get(name);
121        if (field != null) {
122            return field.getValue(doc);
123        }
124        // may be a a property xpath
125        if (name.indexOf(':') > -1) {
126            return doc.getProperty(name);
127        }
128        // may be a schema name
129        if (doc.hasSchema(name)) {
130            return new SchemaTemplate.DocumentSchema(doc, name);
131        }
132        return UNKNOWN;
133    }
134
135    public Collection<String> keys(DocumentModel doc) {
136        Collection<String> keys = new ArrayList<String>(fields.keySet());
137        keys.addAll(Arrays.asList(doc.getSchemas()));
138        return keys;
139    }
140
141    public Map<String, Field> getFields() {
142        return fields;
143    }
144
145    public boolean isEmpty() {
146        return fields.isEmpty();
147    }
148
149    public int size(DocumentModel doc) {
150        return fields.size() + doc.getSchemas().length;
151    }
152
153    protected static final Field SESSION = new Field() {
154        public final String getName() {
155            return "session";
156        }
157
158        public Object getValue(DocumentModel doc) {
159            return doc.getCoreSession();
160        }
161    };
162
163    protected static final Field ID = new Field() {
164        public final String getName() {
165            return "id";
166        }
167
168        public Object getValue(DocumentModel doc) {
169            return doc.getId();
170        }
171    };
172
173    protected static final Field NAME = new Field() {
174        public final String getName() {
175            return "name";
176        }
177
178        public Object getValue(DocumentModel doc) {
179            return doc.getName();
180        }
181    };
182
183    protected static final Field PATH = new Field() {
184        public final String getName() {
185            return "path";
186        }
187
188        public Object getValue(DocumentModel doc) {
189            return doc.getPathAsString();
190        }
191    };
192
193    protected static final Field TYPE = new Field() {
194        public final String getName() {
195            return "type";
196        }
197
198        public Object getValue(DocumentModel doc) {
199            return doc.getType();
200        }
201    };
202
203    protected static final Field SCHEMAS = new Field() {
204        public final String getName() {
205            return "schemas";
206        }
207
208        public Object getValue(DocumentModel doc) {
209            return doc.getSchemas();
210        }
211    };
212
213    protected static final Field FACETS = new Field() {
214        public final String getName() {
215            return "facets";
216        }
217
218        public Object getValue(DocumentModel doc) {
219            return doc.getFacets();
220        }
221    };
222
223    protected static final Field STATE = new Field() {
224        public final String getName() {
225            return "state";
226        }
227
228        public Object getValue(DocumentModel doc) {
229            return doc.getCurrentLifeCycleState();
230        }
231    };
232
233    protected static final Field LOCKED = new Field() {
234        public final String getName() {
235            return "isLocked";
236        }
237
238        public Object getValue(DocumentModel doc) {
239            return doc.isLocked();
240        }
241    };
242
243    protected static final Field LIFE_CYCLE_STATE = new Field() {
244        public final String getName() {
245            return "lifeCycleState";
246        }
247
248        public Object getValue(DocumentModel doc) {
249            return doc.getCurrentLifeCycleState();
250        }
251    };
252
253    protected static final Field LIFE_CYCLE_POLICY = new Field() {
254        public final String getName() {
255            return "lifeCyclePolicy";
256        }
257
258        public Object getValue(DocumentModel doc) {
259            return doc.getLifeCyclePolicy();
260        }
261    };
262
263    protected static final Field ALLOWED_STATE_TRANSITIONS = new Field() {
264        public final String getName() {
265            return "allowedStateTransitions";
266        }
267
268        public Object getValue(DocumentModel doc) {
269            return doc.getAllowedStateTransitions();
270        }
271    };
272
273    protected static final Field IS_FOLDER = new Field() {
274        public final String getName() {
275            return "isFolder";
276        }
277
278        public Object getValue(DocumentModel doc) {
279            return doc.getFacets().contains(FacetNames.FOLDERISH);
280        }
281    };
282
283    protected static final Field TITLE = new Field() {
284        public String getName() {
285            return "title";
286        }
287
288        public Object getValue(DocumentModel doc) {
289            return doc.getTitle();
290        }
291    };
292
293    protected static final Field AUTHOR = new Field() {
294        public String getName() {
295            return "author";
296        }
297
298        public Object getValue(DocumentModel doc) {
299            try {
300                return doc.getPropertyValue("dc:creator");
301            } catch (PropertyNotFoundException e) {
302                // ignore
303            }
304            return null;
305        }
306    };
307
308    protected static final Field CREATED = new Field() {
309        public String getName() {
310            return "created";
311        }
312
313        public Object getValue(DocumentModel doc) {
314            try {
315                Calendar cal = (Calendar) doc.getPropertyValue("dc:created");
316                if (cal != null) {
317                    return cal.getTime();
318                }
319            } catch (PropertyNotFoundException e) {
320                // ignore
321            }
322            return null;
323        }
324    };
325
326    protected static final Field MODIFIED = new Field() {
327        public String getName() {
328            return "modified";
329        }
330
331        public Object getValue(DocumentModel doc) {
332            try {
333                Calendar cal = (Calendar) doc.getPropertyValue("dc:modified");
334                if (cal != null) {
335                    return cal.getTime();
336                }
337            } catch (PropertyNotFoundException e) {
338                // ignore
339            }
340            return null;
341        }
342    };
343
344    protected static final Field CONTENT = new Field() {
345        public String getName() {
346            return "content";
347        }
348
349        public Object getValue(DocumentModel doc) {
350            try {
351                Blob blob = (Blob) doc.getPropertyValue("file:content");
352                if (blob != null) {
353                    return blob;
354                }
355            } catch (PropertyNotFoundException e) {
356                // ignore
357            }
358            return Blobs.createBlob("");
359        }
360    };
361
362    protected static final Field SID = new Field() {
363        public String getName() {
364            return "sessionId";
365        }
366
367        public Object getValue(DocumentModel doc) {
368            return doc.getSessionId();
369        }
370    };
371
372    protected static final Field REPOSITORY = new Field() {
373        public String getName() {
374            return "repository";
375        }
376
377        public Object getValue(DocumentModel doc) {
378            return doc.getRepositoryName();
379        }
380    };
381
382    protected static final Field PARENT = new Field() {
383        public String getName() {
384            return "parent";
385        }
386
387        public Object getValue(DocumentModel doc) {
388            CoreSession session = doc.getCoreSession();
389            return session.getParentDocument(doc.getRef());
390        }
391    };
392
393    protected static final Field CHILDREN = new Field() {
394        public String getName() {
395            return "children";
396        }
397
398        public Object getValue(DocumentModel doc) {
399            CoreSession session = doc.getCoreSession();
400            return session.getChildren(doc.getRef());
401        }
402    };
403
404    protected static final Field REF = new Field() {
405        public String getName() {
406            return "ref";
407        }
408
409        public Object getValue(DocumentModel doc) {
410            return doc.getRef();
411        }
412    };
413
414    protected static final Field VERSIONS = new Field() {
415        public String getName() {
416            return "versions";
417        }
418
419        public Object getValue(DocumentModel doc) {
420            CoreSession session = doc.getCoreSession();
421            return session.getVersions(doc.getRef());
422        }
423    };
424
425    protected static final Field PROXIES = new Field() {
426        public String getName() {
427            return "proxies";
428        }
429
430        public Object getValue(DocumentModel doc) {
431            CoreSession session = doc.getCoreSession();
432            return session.getProxies(doc.getRef(), null);
433        }
434    };
435
436    protected static final Field VERSION_LABEL = new Field() {
437        public String getName() {
438            return "versionLabel";
439        }
440
441        public Object getValue(DocumentModel doc) {
442            return doc.getVersionLabel();
443        }
444    };
445
446    protected static final Field SOURCE_ID = new Field() {
447        public String getName() {
448            return "sourceId";
449        }
450
451        public Object getValue(DocumentModel doc) {
452            return doc.getSourceId();
453        }
454    };
455
456    /**
457     * The singleton instance that should be used by clients. Warn that this static field must be defined at the end of
458     * the class after any other field class since it will try to register these fields (otherwise fields will not be
459     * defined yet at the time of the initialization of that static member
460     */
461    public static final DefaultDocumentView DEFAULT = new DefaultDocumentView();
462
463}