001/*
002 * JGrapes Event Driven Framework
003 * Copyright (C) 2017-2018 Michael N. Lipp
004 * 
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Affero General Public License as published by 
007 * the Free Software Foundation; either version 3 of the License, or 
008 * (at your option) any later version.
009 * 
010 * This program is distributed in the hope that it will be useful, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
013 * for more details.
014 * 
015 * You should have received a copy of the GNU Affero General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jgrapes.portal.base.events;
020
021import java.io.IOException;
022import java.io.Writer;
023import java.util.Arrays;
024import java.util.Collections;
025import java.util.HashSet;
026import java.util.Set;
027import java.util.concurrent.ExecutionException;
028import java.util.concurrent.Future;
029
030import org.jgrapes.portal.base.Portlet.RenderMode;
031
032/**
033 * A base class for portal commands Sent to the portal page for 
034 * adding or updating a complete portlet representation. This class
035 * maintains all required information except the actual content
036 * (the HTML) which must be provided by the derived classes.
037 */
038public abstract class RenderPortlet extends PortalCommand {
039
040    private static final Set<RenderMode> DEFAULT_SUPPORTED
041        = Collections.unmodifiableSet(new HashSet<>(
042            Arrays.asList(new RenderMode[] { RenderMode.Preview })));
043
044    private final Class<?> portletClass;
045    private final String portletId;
046    private RenderMode renderMode = RenderMode.Preview;
047    private Set<RenderMode> supportedModes = DEFAULT_SUPPORTED;
048    private boolean foreground;
049
050    /**
051     * Creates a new event.
052     * 
053     * @param portletClass the portlet class
054     * @param portletId the id of the portlet
055     */
056    public RenderPortlet(Class<?> portletClass, String portletId) {
057        this.portletClass = portletClass;
058        this.portletId = portletId;
059    }
060
061    /**
062     * Returns the portlet class as specified on creation.
063     *
064     * @return the class
065     */
066    public Class<?> portletClass() {
067        return portletClass;
068    }
069
070    /**
071     * Returns the portlet id as specified on creation.
072     * 
073     * @return the portlet id
074     */
075    public String portletId() {
076        return portletId;
077    }
078
079    /**
080     * Set the render mode. The default value is {@link RenderMode#Preview}.
081     * 
082     * @param renderMode the render mode to set
083     * @return the event for easy chaining
084     */
085    public RenderPortlet setRenderMode(RenderMode renderMode) {
086        this.renderMode = renderMode;
087        return this;
088    }
089
090    /**
091     * Returns the render mode.
092     * 
093     * @return the render mode
094     */
095    public RenderMode renderMode() {
096        return renderMode;
097    }
098
099    /**
100     * Set the supported render modes. The default value is 
101     * {@link RenderMode#Preview}.
102     * 
103     * @param supportedModes the supported render modes to set
104     * @return the event for easy chaining
105     */
106    public RenderPortlet setSupportedModes(Set<RenderMode> supportedModes) {
107        this.supportedModes = supportedModes;
108        return this;
109    }
110
111    /**
112     * Add the given render mode to the supported render modes.
113     * 
114     * @param supportedMode the supported render modes to add
115     * @return the event for easy chaining
116     */
117    public RenderPortlet addSupportedMode(RenderMode supportedMode) {
118        if (supportedModes == DEFAULT_SUPPORTED) { // NOPMD, check identity
119            supportedModes = new HashSet<>(DEFAULT_SUPPORTED);
120        }
121        supportedModes.add(supportedMode);
122        return this;
123    }
124
125    /**
126     * Returns the supported modes.
127     * 
128     * @return the supported modes
129     */
130    public Set<RenderMode> supportedRenderModes() {
131        return supportedModes;
132    }
133
134    /**
135     * Id set, the tab with the portlet is put in the foreground
136     * when the portlet is rendered. The default value is `false`.
137     * 
138     * @param foreground if set, the portlet is put in foreground
139     * @return the event for easy chaining
140     */
141    public RenderPortlet setForeground(boolean foreground) {
142        this.foreground = foreground;
143        return this;
144    }
145
146    /**
147     * Indicates if portelt is to be put in foreground.
148     * 
149     * @return the result
150     */
151    public boolean isForeground() {
152        return foreground;
153    }
154
155    /**
156     * Provides the HTML that displays the portlet 
157     * on the page.
158     * 
159     * @return the HTML
160     */
161    public abstract Future<String> content();
162
163    /**
164     * Writes the JSON notification to the given writer.
165     *
166     * @param writer the writer
167     * @throws ExecutionException 
168     * @throws InterruptedException 
169     */
170    @Override
171    public void toJson(Writer writer)
172            throws InterruptedException, IOException {
173        try {
174            toJson(writer, "updatePortlet", portletId(), renderMode().name(),
175                supportedRenderModes().stream().map(RenderMode::name)
176                    .toArray(size -> new String[size]),
177                content().get(), isForeground());
178        } catch (ExecutionException e) {
179            throw new IOException(e);
180        }
181    }
182}