package org.molgenis.framework.ui;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.molgenis.MolgenisOptions;
import org.molgenis.framework.db.Database;
import org.molgenis.framework.security.Login;
import org.molgenis.framework.server.MolgenisContext;
import org.molgenis.framework.server.MolgenisRequest;
import org.molgenis.framework.ui.ScreenModel.Show;
import org.molgenis.framework.ui.html.FreemarkerInput;
import org.molgenis.framework.ui.html.HtmlSettings;
import org.molgenis.framework.ui.html.RichtextInput;
import org.molgenis.framework.ui.html.render.RenderDecorator;
import org.molgenis.util.EmailService;
import org.molgenis.util.FileLink;
import org.molgenis.util.HandleRequestDelegationException;
/**
* The root screen for any MOLGENIS application.
* <p>
* The UserInterface manages a Tree of ScreenControllers. A UserInterface is
* backed by exactly one database (for persistent data) and one Login object
* (taking care of authentication/authorization).
*/
public class ApplicationController extends SimpleScreenController<ApplicationModel>
{
public static final String MOLGENIS_TEMP_PATH = "molgenis_temp";
/** autogenerated */
private static final long serialVersionUID = 3108474555679524568L;
/** */
private static final Logger logger = Logger.getLogger(ApplicationController.class);
/** The login * */
private Login login;
/** The email service used */
private EmailService emailService;
/** Galaxy url */
private String galaxyUrl;
/** Molgenis options from generted */
private MolgenisOptions options;
/** MolgenisContext */
private transient MolgenisContext mc;
/**
* Construct a user interface for a database.
*
* @param login
* for authentication/authorization
*/
public ApplicationController(MolgenisOptions options, Login login)
{
super("molgenis_userinterface_root", null, null); // this is the root of
// the screen tree.
this.setModel(new ApplicationModel(this));
// this.database = db;
this.setLogin(login);
this.setOptions(options);
// set default render decorators
try
{
HtmlSettings.defaultRenderDecorator = (RenderDecorator) Class.forName(options.render_decorator)
.newInstance();
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
catch (InstantiationException e)
{
throw new RuntimeException(e);
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
}
/**
* New constructor for MolgenisGuiService mapped on FrontController
*
* @param options
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public ApplicationController(MolgenisContext mc) throws InstantiationException, IllegalAccessException,
ClassNotFoundException
{
super("molgenis_userinterface_root", null, null); // this is the root of
// the screen tree.
this.setModel(new ApplicationModel(this));
this.setMolgenisContext(mc);
HtmlSettings.defaultRenderDecorator = (RenderDecorator) Class.forName(mc.getUsedOptions().render_decorator)
.newInstance();
}
public ApplicationController(MolgenisOptions options, Login login, EmailService email)
{
this(options, login);
this.setLogin(login);
this.setEmailService(email);
}
/**
* Retrieve the current login
*
* @return Login
*/
public Login getLogin()
{
return login;
}
/**
* Set the Login object that is used for authentication.
*
* @param login
*/
public void setLogin(Login login)
{
this.login = login;
}
/**
* Retrieve the database that is used by this user interface.
*
* @return db the database
*/
// public Database getDatabase()
// {
// return database;
// }
// public void setDatabase(Database database)
// {
// logger.info("replacing database "+this.database+" with "+database);
// this.database = database;
// }
@Override
public FileLink getTempFile() throws IOException
{
// File temp = new File("d:\\Temp\\"+System.currentTimeMillis());
// String tempDir = System.getProperty("java.io.tmpdir");
File temp = File.createTempFile(MOLGENIS_TEMP_PATH, "");
logger.debug("create temp file: " + temp);
return new FileLink(temp, "download/" + temp.getName());
}
/**
* Convenience method that delegates an event to the controller of the
* targetted screen.
*
* @param db
* reference to the database
* @param request
* with the event
*/
public void handleRequest(Database db, MolgenisRequest request) throws Exception, HandleRequestDelegationException
{
this.handleRequest(db, request, null);
}
/**
* Convenience method that delegates the refresh to its ScreenController.
*/
@Override
public void reload(Database db)
{
for (ScreenController<?> s : this.getChildren())
{
try
{
s.reload(db);
}
catch (Exception e)
{
logger.warn(e);
s.getModel().getMessages().add(new ScreenMessage("reload failed: " + e.getMessage(), false));
}
}
}
@Override
public Show handleRequest(Database db, MolgenisRequest request, OutputStream out)
throws HandleRequestDelegationException, Exception
{
logger.info("delegating handleRequest(" + request.toString() + ")");
String screen = request.getString(ScreenModel.INPUT_TARGET);
// action for me?
if (screen != null && screen.equals(this.getName()))
{
if (request.getString("select") != null)
{
// the screen to select
ScreenController<?> selected = this.get(request.getString("select"));
// now we must make sure that alle menu's above select 'me'
ScreenController<?> currentParent = selected.getParent();
ScreenController<?> currentChild = selected;
while (currentParent != null)
{
if (currentParent instanceof MenuController)
{
((MenuController) currentParent).setSelected(currentChild.getName());
}
currentChild = currentParent;
currentParent = currentParent.getParent();
}
}
return Show.SHOW_MAIN;
}
// No target set -> handle centrally.
else
{
if (!request.isNull("GALAXY_URL"))
{
//
// If a user navigated to Molgenis from a session on a Galaxy
// server,
// we keep track of the Galaxy server address, so when this user
// wants
// to send (upload) data to Galaxy we know which one to send the
// data to.
// (In fact we do not send the data directly, but an URL that
// can be used
// by Galaxy to fetch the data)
//
this.setGalaxyUrl(request.getString("GALAXY_URL"));
logger.info("User was forwarded to Molgenis running @ " + request.getAppLocation());
logger.info("User was forwarded to Molgenis by Galaxy running @ " + this.getGalaxyUrl());
}
}
// Delegate
ScreenController<?> target = get(screen);
if (target != null)
{
if (!target.equals(this)) return target.handleRequest(db, request, null);
}
else
logger.debug("handleRequest(" + request + "): no request needs to be handled");
return Show.SHOW_MAIN;
}
@Override
public EmailService getEmailService()
{
return emailService;
}
public void setEmailService(EmailService emailService)
{
this.emailService = emailService;
}
public void clearAllMessages()
{
for (ScreenController<?> s : this.getAllChildren())
{
s.getModel().getMessages().clear();
}
}
/**
* Get the database object for this application
*
* @return
* @throws Exception
*/
@Override
public Database getDatabase()
{
throw new UnsupportedOperationException("getDatabase must be implemented for use");
}
public String getGalaxyUrl()
{
return galaxyUrl;
}
public void setGalaxyUrl(String galaxyUrl)
{
this.galaxyUrl = galaxyUrl;
}
@Override
@Deprecated
// why is this here?
public String getCustomHtmlHeaders()
{
// TODO: this should be made more generic
return new FreemarkerInput("dummy").getCustomHtmlHeaders() + new RichtextInput("dummy").getCustomHtmlHeaders()
+ super.getCustomHtmlHeaders();
}
@Deprecated
public MolgenisOptions getOptions()
{
return options;
}
@Deprecated
public void setOptions(MolgenisOptions options)
{
this.options = options;
}
public MolgenisContext getMolgenisContext()
{
return mc;
}
public void setMolgenisContext(MolgenisContext mc)
{
this.mc = mc;
}
@Override
public ScreenView getView()
{
return new FreemarkerView("ApplicationView.ftl", this.getModel());
}
/**
* Store values in a map, much like session attributes. The reaason to do
* this is because session variables are not always reachable inside plugin
* functions, and if they are, it is complex and convoluted because this
* applicationcontroller itself is already stored as a session attribute!
* (see: MolgenisGuiService.java)
*/
public Map<String, Object> sessionVariables = new HashMap<String, Object>();
}