
org.nakedobjects.plugins.dnd.bootstrap.DndViewer Maven / Gradle / Ivy
The newest version!
package org.nakedobjects.plugins.dnd.bootstrap;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.StringTokenizer;
import org.apache.log4j.Logger;
import org.nakedobjects.metamodel.adapter.NakedObject;
import org.nakedobjects.metamodel.authentication.AuthenticationSession;
import org.nakedobjects.metamodel.commons.exceptions.NakedObjectException;
import org.nakedobjects.metamodel.commons.factory.InstanceCreationException;
import org.nakedobjects.metamodel.commons.factory.InstanceFactory;
import org.nakedobjects.metamodel.config.ConfigurationException;
import org.nakedobjects.plugins.dnd.HelpViewer;
import org.nakedobjects.plugins.dnd.Toolkit;
import org.nakedobjects.plugins.dnd.View;
import org.nakedobjects.plugins.dnd.ViewRequirement;
import org.nakedobjects.plugins.dnd.ViewSpecification;
import org.nakedobjects.plugins.dnd.viewer.AwtToolkit;
import org.nakedobjects.plugins.dnd.viewer.LoginDialog;
import org.nakedobjects.plugins.dnd.viewer.ShutdownListener;
import org.nakedobjects.plugins.dnd.viewer.SkylarkViewFactory;
import org.nakedobjects.plugins.dnd.viewer.ViewerFrame;
import org.nakedobjects.plugins.dnd.viewer.XViewer;
import org.nakedobjects.plugins.dnd.viewer.basic.DragContentSpecification;
import org.nakedobjects.plugins.dnd.viewer.basic.EmptyField;
import org.nakedobjects.plugins.dnd.viewer.basic.InnerWorkspaceSpecification;
import org.nakedobjects.plugins.dnd.viewer.basic.PasswordFieldSpecification;
import org.nakedobjects.plugins.dnd.viewer.basic.RootIconSpecification;
import org.nakedobjects.plugins.dnd.viewer.basic.RootWorkspaceSpecification;
import org.nakedobjects.plugins.dnd.viewer.basic.SubviewIconSpecification;
import org.nakedobjects.plugins.dnd.viewer.basic.WrappedTextFieldSpecification;
import org.nakedobjects.plugins.dnd.viewer.content.PerspectiveContent;
import org.nakedobjects.plugins.dnd.viewer.drawing.Bounds;
import org.nakedobjects.plugins.dnd.viewer.drawing.Location;
import org.nakedobjects.plugins.dnd.viewer.drawing.Size;
import org.nakedobjects.plugins.dnd.viewer.image.ImageFactory;
import org.nakedobjects.plugins.dnd.viewer.list.ExpandableListSpecification;
import org.nakedobjects.plugins.dnd.viewer.list.GridSpecification;
import org.nakedobjects.plugins.dnd.viewer.list.HistogramSpecification;
import org.nakedobjects.plugins.dnd.viewer.list.InternalListSpecification;
import org.nakedobjects.plugins.dnd.viewer.list.SimpleListSpecification;
import org.nakedobjects.plugins.dnd.viewer.list.SummaryListWindowSpecification;
import org.nakedobjects.plugins.dnd.viewer.notifier.ViewUpdateNotifier;
import org.nakedobjects.plugins.dnd.viewer.table.WindowTableSpecification;
import org.nakedobjects.plugins.dnd.viewer.tree.ListWithDetailSpecification;
import org.nakedobjects.plugins.dnd.viewer.tree.TreeSpecification;
import org.nakedobjects.plugins.dnd.viewer.tree.TreeWithDetailSpecification;
import org.nakedobjects.plugins.dnd.viewer.util.Properties;
import org.nakedobjects.plugins.dnd.viewer.view.extendedform.TwoPartViewSpecification;
import org.nakedobjects.plugins.dnd.viewer.view.field.CheckboxField;
import org.nakedobjects.plugins.dnd.viewer.view.field.ColorField;
import org.nakedobjects.plugins.dnd.viewer.view.field.ImageField;
import org.nakedobjects.plugins.dnd.viewer.view.field.TextFieldSpecification;
import org.nakedobjects.plugins.dnd.viewer.view.form.WindowFormSpecification;
import org.nakedobjects.plugins.dnd.viewer.view.help.InternalHelpViewer;
import org.nakedobjects.plugins.dnd.viewer.view.message.DetailedMessageViewSpecification;
import org.nakedobjects.plugins.dnd.viewer.view.message.MessageDialogSpecification;
import org.nakedobjects.plugins.dnd.viewer.view.specification.ServiceIconSpecification;
import org.nakedobjects.runtime.authentication.AuthenticationRequest;
import org.nakedobjects.runtime.authentication.AuthenticationRequestPassword;
import org.nakedobjects.runtime.authentication.standard.exploration.AuthenticationRequestExploration;
import org.nakedobjects.runtime.authentication.standard.fixture.AuthenticationRequestLogonFixture;
import org.nakedobjects.runtime.context.NakedObjectsContext;
import org.nakedobjects.runtime.userprofile.UserProfile;
import org.nakedobjects.runtime.viewer.NakedObjectsViewerAbstract;
public class DndViewer extends NakedObjectsViewerAbstract {
private static final Logger LOG = Logger.getLogger(DndViewer.class);
private static final String SPECIFICATION_BASE = Properties.PROPERTY_BASE + "specification.";
private ViewUpdateNotifier updateNotifier;
private ViewerFrame frame;
private XViewer viewer;
private ShutdownListener shutdownListener;
private Bounds bounds;
private HelpViewer helpViewer;
private boolean acceptingLogIns = true;
// ////////////////////////////////////
// shutdown
// ////////////////////////////////////
@Override
public void shutdown() {
System.exit(0);
}
private Bounds calculateBounds(final Dimension screenSize) {
int maxWidth = screenSize.width;
final int maxHeight = screenSize.height;
if ((screenSize.width / screenSize.height) >= 2) {
final int f = screenSize.width / screenSize.height;
maxWidth = screenSize.width / f;
}
final int width = maxWidth - 80;
final int height = maxHeight - 80;
final int x = 40;
final int y = 40;
Size defaultWindowSize = new Size(width, height);
defaultWindowSize.limitWidth(800);
defaultWindowSize.limitHeight(600);
final Size size = Properties.getSize(Properties.PROPERTY_BASE + "initial.size", defaultWindowSize);
final Location location = Properties.getLocation(Properties.PROPERTY_BASE + "initial.location", new Location(x, y));
return new Bounds(location, size);
}
private ViewSpecification loadSpecification(final String name, final Class> cls) {
final String factoryName = NakedObjectsContext.getConfiguration().getString(SPECIFICATION_BASE + name);
ViewSpecification spec;
if (factoryName != null) {
spec = InstanceFactory.createInstance(factoryName, ViewSpecification.class);
} else {
spec = InstanceFactory.createInstance(cls.getName(), ViewSpecification.class);
}
return spec;
}
private synchronized void logOut() {
LOG.info("user log out");
saveDesktop();
final AuthenticationSession session = NakedObjectsContext.getAuthenticationSession();
getAuthenticationManager().closeSession(session);
viewer.close();
notify();
}
private void saveDesktop() {
if (!NakedObjectsContext.inSession()) {
// can't do anything
return;
}
// TODO get hold of desktop objects
NakedObjectsContext.getUserProfileLoader().saveSession(new ArrayList());
}
protected void quit() {
LOG.info("user quit");
saveDesktop();
acceptingLogIns = false;
shutdown();
}
@Override
public synchronized void init() {
super.init();
new ImageFactory(NakedObjectsContext.getTemplateImageLoader());
new AwtToolkit();
setupViewFactory();
setShutdownListener(new ShutdownListener() {
public void logOut() {
DndViewer.this.logOut();
}
public void quit() {
DndViewer.this.quit();
}
});
updateNotifier = new ViewUpdateNotifier();
if (updateNotifier == null) {
throw new NullPointerException("No update notifier set for " + this);
}
if (shutdownListener == null) {
throw new NullPointerException("No shutdown listener set for " + this);
}
while (acceptingLogIns) {
if (login()) {
openViewer();
try {
wait();
} catch (final InterruptedException e) {}
} else {
quit();
}
}
}
// ////////////////////////////////////
// login
// ////////////////////////////////////
// TODO: nasty
private boolean loggedInUsingLogonFixture = false;
/**
* TODO: there is similar code in AuthenticationSessionLookupStrategyDefault;
* should try to combine somehow...
*/
private boolean login() {
AuthenticationRequest request = determineRequestIfPossible();
// we may have enough to get a session
AuthenticationSession session = getAuthenticationManager().authenticate(request);
clearAuthenticationRequestViaArgs();
// otherwise, keep prompting
String message = null;
while (session == null) {
if (request == null) {
request = promptForAuthenticationDetails(message);
}
if (request == null) {
return false;
}
session = getAuthenticationManager().authenticate(request);
// in case we need to try again
request = null;
message = "Invalid user/password; please try again";
}
NakedObjectsContext.openSession(session);
return true;
}
private AuthenticationRequest determineRequestIfPossible() {
AuthenticationRequest request;
// command line args
request = getAuthenticationRequestViaArgs();
// exploration
if (request == null && getDeploymentType().isExploring()) {
request = new AuthenticationRequestExploration(getLogonFixture());
}
// logon fixture provided
if (request == null && getLogonFixture() != null && !loggedInUsingLogonFixture) {
loggedInUsingLogonFixture = true;
request = new AuthenticationRequestLogonFixture(getLogonFixture());
}
return request;
}
private AuthenticationRequest promptForAuthenticationDetails(String message) {
final LoginDialog dialog = new LoginDialog(message);
dialog.setVisible(true);
dialog.toFront();
if (dialog.login()) {
dialog.setVisible(false);
dialog.dispose();
return new AuthenticationRequestPassword(dialog.getUser(), dialog.getPassword());
} else {
dialog.setVisible(false);
dialog.dispose();
return null;
}
}
private void openViewer() {
frame = new ViewerFrame();
if (bounds == null) {
bounds = calculateBounds(frame.getToolkit().getScreenSize());
}
frame.pack(); // forces insets to be calculated, hence need to then set bounds
frame.setBounds(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
viewer = (XViewer) Toolkit.getViewer();
viewer.setRenderingArea(frame);
viewer.setUpdateNotifier(updateNotifier);
viewer.setListener(shutdownListener);
viewer.setExploration(isInExplorationMode());
if (helpViewer == null) {
helpViewer = new InternalHelpViewer(viewer);
}
viewer.setHelpViewer(helpViewer);
frame.setViewer(viewer);
final AuthenticationSession currentSession = NakedObjectsContext.getAuthenticationSession();
if (currentSession == null) {
throw new NullPointerException("No session for " + this);
}
final UserProfile userProfiler = NakedObjectsContext.getUserProfile();
// TODO viewer should be shown during init() (so login can take place on main window, and can quit
// before
// logging in), and should be updated during start to show context.
// TODO resolving should be done by the views?
// resolveApplicationContextCollection(rootObject, "services");
// resolveApplicationContextCollection(rootObject, "objects");
final RootWorkspaceSpecification spec = new RootWorkspaceSpecification();
final PerspectiveContent content = new PerspectiveContent(userProfiler.getPerspective());
if (spec.canDisplay(content, new ViewRequirement(content, ViewRequirement.CLOSED))) {
// View view = spec.createView(new RootObject(rootObject), null);
final View view = spec.createView(content, null);
viewer.setRootView(view);
} else {
throw new NakedObjectException();
}
viewer.init();
final String name = userProfiler.getPerspective().getName();
frame.setTitle(name);
frame.init();
viewer.initSize();
viewer.scheduleRepaint();
frame.setVisible(true);
frame.toFront();
}
private boolean isInExplorationMode() {
return getDeploymentType().isExploring();
}
public void setBounds(final Bounds bounds) {
this.bounds = bounds;
}
public void setHelpViewer(final HelpViewer helpViewer) {
this.helpViewer = helpViewer;
}
public void setShutdownListener(final ShutdownListener shutdownListener) {
this.shutdownListener = shutdownListener;
}
private void setupViewFactory() throws ConfigurationException, InstanceCreationException {
final SkylarkViewFactory viewFactory = (SkylarkViewFactory) Toolkit.getViewFactory();
LOG.debug("setting up default views (provided by the framework)");
/*
* viewFactory.addValueFieldSpecification(loadSpecification("field.option",
* OptionSelectionField.Specification.class));
* viewFactory.addValueFieldSpecification(loadSpecification("field.percentage",
* PercentageBarField.Specification.class));
* viewFactory.addValueFieldSpecification(loadSpecification("field.timeperiod",
* TimePeriodBarField.Specification.class));
*/
viewFactory.addSpecification(loadSpecification("field.image", ImageField.Specification.class));
viewFactory.addSpecification(loadSpecification("field.color", ColorField.Specification.class));
viewFactory.addSpecification(loadSpecification("field.password", PasswordFieldSpecification.class));
viewFactory.addSpecification(loadSpecification("field.wrappedtext", WrappedTextFieldSpecification.class));
viewFactory.addSpecification(loadSpecification("field.checkbox", CheckboxField.Specification.class));
viewFactory.addSpecification(loadSpecification("field.text", TextFieldSpecification.class));
viewFactory.addSpecification(new RootWorkspaceSpecification());
viewFactory.addSpecification(new InnerWorkspaceSpecification());
if (NakedObjectsContext.getConfiguration().getBoolean(SPECIFICATION_BASE + "defaults", true)) {
viewFactory.addSpecification(new InternalListSpecification());
viewFactory.addSpecification(new SimpleListSpecification());
viewFactory.addSpecification(new SummaryListWindowSpecification());
viewFactory.addSpecification(new GridSpecification());
// TBA viewFactory.addSpecification(new ListWithExpandableElementsSpecification());
// TBA viewFactory.addSpecification(new CalendarSpecification());
viewFactory.addSpecification(new ListWithDetailSpecification());
viewFactory.addSpecification(new HistogramSpecification());
viewFactory.addSpecification(new TreeWithDetailSpecification());
viewFactory.addSpecification(new WindowFormSpecification());
viewFactory.addSpecification(new WindowTableSpecification());
// TBA viewFactory.addSpecification(new WindowExpandableFormSpecification());
viewFactory.addSpecification(new TwoPartViewSpecification());
// TBA viewFactory.addSpecification(new ExtendedFormSpecification());
// TBA viewFactory.addSpecification(new FormWithDetailSpecification());
viewFactory.addSpecification(new TreeSpecification());
// TODO allow window form to be used for objects with limited number of collections
// viewFactory.addSpecification(new TreeWithDetailSpecification(0, 3));
// viewFactory.addCompositeRootViewSpecification(new
// BarchartSpecification());
// viewFactory.addCompositeRootViewSpecification(new
// GridSpecification());
}
viewFactory.addSpecification(new MessageDialogSpecification());
viewFactory.addSpecification(new DetailedMessageViewSpecification());
viewFactory.addEmptyFieldSpecification(loadSpecification("field.empty", EmptyField.Specification.class));
viewFactory.addSpecification(loadSpecification("icon.object", RootIconSpecification.class));
viewFactory.addSpecification(loadSpecification("icon.subview", SubviewIconSpecification.class));
viewFactory.addSpecification(loadSpecification("icon.collection", ExpandableListSpecification.class));
viewFactory.addSpecification(loadSpecification("icon.service", SubviewIconSpecification.class));
viewFactory.addSpecification(loadSpecification("icon.service", ServiceIconSpecification.class));
viewFactory.setDragContentSpecification(loadSpecification("drag-content", DragContentSpecification.class));
final String viewParams = NakedObjectsContext.getConfiguration().getString(SPECIFICATION_BASE + "view");
if (viewParams != null) {
final StringTokenizer st = new StringTokenizer(viewParams, ",");
while (st.hasMoreTokens()) {
final String specName = st.nextToken().trim();
if (specName != null && !specName.trim().equals("")) {
try {
ViewSpecification spec;
spec = (ViewSpecification) InstanceFactory.createInstance(specName);
LOG.info("adding view specification: " + spec);
viewFactory.addSpecification(spec);
} catch (final InstanceCreationException e) {
// LOG.error("failed to find view specification class " + specName);
throw e;
}
}
}
}
}
}
// Copyright (c) Naked Objects Group Ltd.
© 2015 - 2025 Weber Informatics LLC | Privacy Policy