001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     bstefanescu
011 *
012 * $Id$
013 */
014
015package org.nuxeo.ecm.platform.rendering.wiki;
016
017import java.io.BufferedReader;
018import java.io.File;
019import java.io.IOException;
020import java.io.InputStream;
021import java.io.InputStreamReader;
022import java.io.Reader;
023import java.io.StringReader;
024import java.io.StringWriter;
025import java.io.Writer;
026import java.net.URL;
027import java.util.Map;
028
029import org.apache.commons.io.IOUtils;
030import org.nuxeo.ecm.core.api.model.Property;
031import org.nuxeo.ecm.platform.rendering.api.RenderingException;
032import org.nuxeo.ecm.platform.rendering.fm.FreemarkerEngine;
033import org.nuxeo.ecm.platform.rendering.fm.adapters.ComplexPropertyTemplate;
034import org.nuxeo.ecm.platform.rendering.wiki.extensions.FreemarkerMacro;
035import org.wikimodel.wem.WikiParserException;
036
037import freemarker.core.Environment;
038import freemarker.template.SimpleScalar;
039import freemarker.template.TemplateDirectiveBody;
040import freemarker.template.TemplateDirectiveModel;
041import freemarker.template.TemplateException;
042import freemarker.template.TemplateModel;
043import freemarker.template.TemplateModelException;
044
045/**
046 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
047 */
048public class WikiTransformer implements TemplateDirectiveModel {
049
050    protected final WikiSerializer serializer;
051
052    public WikiTransformer() {
053        this(new WikiSerializer());
054    }
055
056    public WikiTransformer(WikiSerializer serializer) {
057        this.serializer = serializer;
058        this.serializer.registerMacro(new FreemarkerMacro());
059        // TODO implement and register a JEXL extension
060    }
061
062    public WikiSerializer getSerializer() {
063        return serializer;
064    }
065
066    public void transform(Reader reader, Writer writer) throws RenderingException {
067        try {
068            serializer.serialize(reader, writer);
069        } catch (IOException | WikiParserException e) {
070            throw new RenderingException(e);
071        }
072    }
073
074    public void transform(URL url, Writer writer) throws RenderingException {
075        Reader reader = null;
076        try {
077            InputStream in = url.openStream();
078            reader = new BufferedReader(new InputStreamReader(in));
079            transform(reader, writer);
080        } catch (IOException e) {
081            throw new RenderingException(e);
082        } finally {
083            IOUtils.closeQuietly(reader);
084        }
085    }
086
087    @Override
088    @SuppressWarnings("rawtypes")
089    public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
090            throws TemplateException, IOException {
091
092        // TODO: not used for now.
093        String syntax = null;
094        SimpleScalar scalar = (SimpleScalar) params.get("syntax");
095        if (scalar != null) {
096            syntax = scalar.getAsString();
097        }
098
099        scalar = (SimpleScalar) params.get("src");
100        String src = null;
101        if (scalar != null) {
102            src = scalar.getAsString();
103        }
104
105        ComplexPropertyTemplate complex = (ComplexPropertyTemplate) params.get("property");
106        Property property = null;
107        if (complex != null) {
108            property = (Property) complex.getAdaptedObject(null);
109        }
110
111        FreemarkerEngine engine = (FreemarkerEngine) env.getCustomAttribute(FreemarkerEngine.RENDERING_ENGINE_KEY);
112        if (engine == null) {
113            throw new TemplateModelException("Not in a nuxeo rendering context");
114        }
115
116        try {
117            if (property != null) {
118                // TODO XXX implement property support (with caching)
119                throw new UnsupportedOperationException("Not Yet Implemented");
120                // URL url = PropertyURL.getURL(ctxModel.getDocument(), property.getPath());
121                // tr.transform(url, env.getOut(), ctxModel.getContext());
122            } else if (src == null) {
123                if (body == null) {
124                    throw new TemplateModelException(
125                            "Transform directive must have either a content either a valid 'src' attribute");
126                }
127                // render body to get back the result
128                StringWriter writer = new StringWriter();
129                body.render(writer);
130                String content = writer.getBuffer().toString();
131                transform(new StringReader(content), env.getOut());
132            } else {
133                if (src.contains(":/")) {
134                    URL url = engine.getResourceLocator().getResourceURL(src);
135                    if (url != null) {
136                        transform(url, env.getOut());
137                    } else {
138                        throw new IllegalArgumentException("Cannot resolve the src attribute: " + src);
139                    }
140                } else {
141                    File file = engine.getResourceLocator().getResourceFile(src);
142                    if (file != null) {
143                        transform(file.toURI().toURL(), env.getOut());
144                    } else {
145                        throw new IllegalArgumentException("Cannot resolve the src attribute: " + src);
146                    }
147                }
148            }
149        } catch (RenderingException e) {
150            throw new TemplateException("Running wiki transformer failed", e, env);
151        }
152    }
153
154}