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