001/*
002 * (C) Copyright 2012 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 *     Thierry Delprat
018 */
019package org.nuxeo.template.processors;
020
021import java.io.IOException;
022import java.io.Serializable;
023import java.util.Collections;
024import java.util.Date;
025import java.util.List;
026import java.util.Map;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030import org.nuxeo.ecm.core.api.Blob;
031import org.nuxeo.ecm.core.api.PropertyException;
032import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
033import org.nuxeo.ecm.core.api.model.Property;
034import org.nuxeo.ecm.core.convert.api.ConversionService;
035import org.nuxeo.ecm.core.schema.types.Type;
036import org.nuxeo.ecm.core.schema.types.primitives.BooleanType;
037import org.nuxeo.ecm.core.schema.types.primitives.DateType;
038import org.nuxeo.ecm.core.schema.types.primitives.StringType;
039import org.nuxeo.ecm.platform.rendering.fm.adapters.DocumentObjectWrapper;
040import org.nuxeo.runtime.api.Framework;
041import org.nuxeo.template.api.ContentInputType;
042import org.nuxeo.template.api.InputType;
043import org.nuxeo.template.api.TemplateInput;
044import org.nuxeo.template.api.adapters.TemplateBasedDocument;
045
046import freemarker.template.TemplateModelException;
047
048public abstract class AbstractBindingResolver implements InputBindingResolver {
049
050    protected Log log = LogFactory.getLog(AbstractBindingResolver.class);
051
052    protected abstract Object handleLoop(String paramName, Object value);
053
054    protected abstract Object handlePictureField(String paramName, Blob blobValue);
055
056    protected abstract void handleBlobField(String paramName, Blob blobValue);
057
058    protected String handleHtmlField(String paramName, String htmlValue) {
059        return HtmlBodyExtractor.extractHtmlBody(htmlValue);
060    }
061
062    protected DocumentObjectWrapper nuxeoWrapper = new DocumentObjectWrapper(null);
063
064    public AbstractBindingResolver() {
065        super();
066    }
067
068    protected DocumentObjectWrapper getWrapper() {
069        return nuxeoWrapper;
070    }
071
072    @Override
073    public void resolve(List<TemplateInput> inputParams, Map<String, Object> context,
074            TemplateBasedDocument templateBasedDocument) {
075
076        for (TemplateInput param : inputParams) {
077            try {
078                if (param.isSourceValue()) {
079                    if (param.getType() == InputType.Content) {
080                        if (ContentInputType.HtmlPreview.getValue().equals(param.getSource())) {
081                            BlobHolder bh = templateBasedDocument.getAdaptedDoc().getAdapter(BlobHolder.class);
082                            String htmlValue = handleHtmlField(param.getName(), getHtmlValue(bh));
083                            context.put(param.getName(), htmlValue);
084                            continue;
085                        } else if (ContentInputType.BlobContent.getValue().equals(param.getSource())) {
086                            Object propValue = templateBasedDocument.getAdaptedDoc().getPropertyValue(param.getSource());
087                            if (propValue != null && propValue instanceof Blob) {
088                                Blob blobValue = (Blob) propValue;
089                                context.put(param.getName(), blobValue.getString());
090                                handleBlobField(param.getName(), blobValue);
091                            }
092                        } else {
093                            Object propValue = templateBasedDocument.getAdaptedDoc().getPropertyValue(param.getSource());
094                            if (propValue instanceof String) {
095                                String stringContent = (String) propValue;
096                                String htmlValue = handleHtmlField(param.getName(), stringContent);
097                                context.put(param.getName(), htmlValue);
098                            }
099                        }
100                    }
101                    Property property = null;
102                    try {
103                        property = templateBasedDocument.getAdaptedDoc().getProperty(param.getSource());
104                    } catch (PropertyException e) {
105                        log.warn("Unable to ready property " + param.getSource(), e);
106                    }
107
108                    Serializable value = null;
109                    if (property != null) {
110                        value = property.getValue();
111                    }
112
113                    if (value != null) {
114                        if (param.getType() != InputType.Content) {
115                            if (Blob.class.isAssignableFrom(value.getClass())) {
116                                Blob blob = (Blob) value;
117                                if (param.getType() == InputType.PictureProperty) {
118                                    if (blob.getMimeType() == null || "".equals(blob.getMimeType().trim())) {
119                                        blob.setMimeType("image/jpeg");
120                                    }
121                                    context.put(param.getName(), handlePictureField(param.getName(), blob));
122                                }
123                            } else {
124                                if (param.isAutoLoop()) {
125                                    // should do the same on all children
126                                    // properties ?
127                                    Object loopVal = handleLoop(param.getName(), property);
128                                    context.put(param.getName(), loopVal);
129                                } else {
130                                    context.put(param.getName(), nuxeoWrapper.wrap(property));
131                                }
132                            }
133                        }
134                    } else {
135                        // no available value, try to find a default one ...
136                        if (property != null) {
137                            Type pType = property.getType();
138                            if (pType.getName().equals(BooleanType.ID)) {
139                                context.put(param.getName(), new Boolean(false));
140                            } else if (pType.getName().equals(DateType.ID)) {
141                                context.put(param.getName(), new Date());
142                            } else if (pType.getName().equals(StringType.ID)) {
143                                context.put(param.getName(), "");
144                            } else if (pType.getName().equals(InputType.Content.getValue())) {
145                                context.put(param.getName(), "");
146                            } else {
147                                context.put(param.getName(), "!NOVALUE!");
148                            }
149                            // handle special case for pictures
150                            if (param.getType() == InputType.PictureProperty) {
151                                context.put(param.getName(), handlePictureField(param.getName(), null));
152                            }
153                        } else {
154                            if (param.getType().equals(InputType.PictureProperty)) {
155                                context.put(param.getName(), handlePictureField(param.getName(), null));
156                            }
157                        }
158                    }
159
160                } else {
161                    if (InputType.StringValue.equals(param.getType())) {
162                        context.put(param.getName(), param.getStringValue());
163                    } else if (InputType.BooleanValue.equals(param.getType())) {
164                        context.put(param.getName(), param.getBooleanValue());
165                    } else if (InputType.DateValue.equals(param.getType())) {
166                        context.put(param.getName(), param.getDateValue());
167                    }
168                }
169            } catch (TemplateModelException | IOException e) {
170                log.warn("Unable to handle binding for param " + param.getName(), e);
171            }
172        }
173    }
174
175    protected String getHtmlValue(BlobHolder bh) throws IOException {
176        if (bh == null) {
177            return "";
178        }
179
180        Blob blob = bh.getBlob();
181        if (blob != null && "text/html".equals(blob.getMimeType())) {
182            return blob.getString();
183        }
184
185        ConversionService conversion = Framework.getService(ConversionService.class);
186        BlobHolder htmlBh = conversion.convertToMimeType("text/html", bh, Collections.emptyMap());
187        if (htmlBh != null) {
188            return htmlBh.getBlob().getString();
189        }
190
191        if (blob != null && blob.getMimeType() != null && blob.getMimeType().startsWith("text/")) {
192            return blob.getString();
193        }
194
195        return "";
196    }
197
198}