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