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