001/*
002 * (C) Copyright 2006-2007 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.template;
023
024import java.util.ArrayList;
025import java.util.Arrays;
026import java.util.HashMap;
027import java.util.List;
028import java.util.Map;
029import java.util.Map.Entry;
030
031import org.nuxeo.ecm.core.api.DocumentModel;
032
033import freemarker.template.AdapterTemplateModel;
034import freemarker.template.ObjectWrapper;
035import freemarker.template.TemplateCollectionModel;
036import freemarker.template.TemplateHashModelEx;
037import freemarker.template.TemplateModel;
038import freemarker.template.TemplateModelException;
039
040/**
041 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
042 */
043public class DocumentModelAdapter implements TemplateHashModelEx, AdapterTemplateModel {
044
045    protected final DocumentModel doc;
046
047    protected final ObjectWrapper wrapper;
048
049    private TemplateCollectionModel keys;
050
051    private int size = -1;
052
053    // id, name, path, type, schemas, facets, system, schema1, schema2, ...
054
055    public DocumentModelAdapter(DocumentModel doc, ObjectWrapper wrapper) {
056        this.doc = doc;
057        this.wrapper = wrapper;
058    }
059
060    public DocumentModelAdapter(DocumentModel doc) {
061        this(doc, ObjectWrapper.DEFAULT_WRAPPER);
062    }
063
064    @Override
065    @SuppressWarnings("rawtypes")
066    public Object getAdaptedObject(Class hint) {
067        return doc;
068    }
069
070    @Override
071    public TemplateModel get(String key) throws TemplateModelException {
072        DocumentFieldAccessor accessor = DocumentFieldAccessor.get(key);
073        if (accessor != null) {
074            return wrapper.wrap(accessor.getValue(doc));
075        }
076        // may be a schema name (doc.dublincore.title)
077        Map<String, Object> properties = doc.getProperties(key);
078        if (properties != null) {
079            return wrapper.wrap(unPrefixedMap(properties));
080        }
081        return wrapper.wrap(null);
082    }
083
084    private static Map<String, Object> unPrefixedMap(Map<String, Object> props) {
085        Map<String, Object> res = new HashMap<String, Object>();
086        for (Entry<String, Object> e : props.entrySet()) {
087            String key = e.getKey();
088            int pos = key.indexOf(':');
089            if (pos > -1) {
090                key = key.substring(pos + 1);
091            }
092            res.put(key, e.getValue());
093        }
094        return res;
095    }
096
097    /**
098     * a doc model is never empty
099     */
100    @Override
101    public boolean isEmpty() throws TemplateModelException {
102        return false;
103    }
104
105    @Override
106    public TemplateCollectionModel keys() throws TemplateModelException {
107        if (keys == null) {
108            List<String> keysCol = new ArrayList<>();
109            keysCol.addAll(DocumentFieldAccessor.getFieldNames());
110            String[] schemas = doc.getSchemas();
111            keysCol.addAll(Arrays.asList(schemas));
112            size = keysCol.size();
113            keys = (TemplateCollectionModel) wrapper.wrap(keysCol);
114        }
115        return keys;
116    }
117
118    @Override
119    public TemplateCollectionModel values() throws TemplateModelException {
120        List<Object> values = new ArrayList<>();
121        for (DocumentFieldAccessor accessor : DocumentFieldAccessor.getAcessors()) {
122            values.add(accessor.getValue(doc));
123        }
124        for (String schema : doc.getSchemas()) {
125            Map<String, Object> properties = doc.getProperties(schema);
126            if (properties != null) {
127                values.add(properties);
128            }
129        }
130        return (TemplateCollectionModel) wrapper.wrap(values);
131    }
132
133    @Override
134    public int size() throws TemplateModelException {
135        if (size == -1) {
136            size = DocumentFieldAccessor.getAcessorsCount() + doc.getSchemas().length;
137        }
138        return size;
139    }
140
141}