package org.jboss.as.console.mbui;
import java.util.HashMap;
import java.util.Map;
import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;
import org.jboss.as.console.client.Console;
import org.jboss.as.console.client.core.Footer;
import org.jboss.as.console.client.domain.model.SimpleCallback;
import org.jboss.as.console.client.rbac.SecurityFramework;
import org.jboss.as.console.mbui.bootstrap.ReadOperationDescriptions;
import org.jboss.as.console.mbui.bootstrap.ReadResourceDescription;
import org.jboss.as.console.mbui.bootstrap.ReificationBootstrap;
import org.jboss.as.console.mbui.reification.pipeline.BuildUserInterfaceStep;
import org.jboss.as.console.mbui.reification.pipeline.ImplicitBehaviourStep;
import org.jboss.as.console.mbui.reification.rbac.RequiredResources;
import org.jboss.ballroom.client.rbac.SecurityContext;
import org.jboss.gwt.flow.client.Async;
import org.jboss.gwt.flow.client.Control;
import org.jboss.gwt.flow.client.Function;
import org.jboss.gwt.flow.client.Outcome;
import org.useware.kernel.gui.behaviour.InteractionCoordinator;
import org.useware.kernel.gui.behaviour.KernelContract;
import org.useware.kernel.gui.behaviour.NavigationDelegate;
import org.useware.kernel.gui.behaviour.StatementContext;
import org.useware.kernel.gui.reification.Context;
import org.useware.kernel.gui.reification.ContextKey;
import org.useware.kernel.gui.reification.pipeline.IntegrityStep;
import org.useware.kernel.gui.reification.pipeline.ReificationPipeline;
import org.useware.kernel.gui.reification.pipeline.UniqueIdCheckStep;
import org.useware.kernel.gui.reification.strategy.ReificationWidget;
import org.useware.kernel.model.Dialog;
import org.useware.kernel.model.scopes.BranchActivation;
import org.useware.kernel.model.structure.QName;
/**
* @author Heiko Braun
* @date 3/22/13
*/
public class Kernel implements NavigationDelegate {
private DialogRepository repository;
private final StatementContext globalContext;
private Map<String, KernelContract> coordinators = new HashMap<String, KernelContract>();
private Map<String, ReificationWidget> cachedWidgets = new HashMap<String, ReificationWidget>();
private String activeDialog;
private final Framework framework;
private boolean enableCache = true;
public Kernel(DialogRepository repository, Framework framework, StatementContext globalContext) {
this.repository = repository;
this.globalContext = globalContext;
this.framework = framework;
}
/**
* Absolute navigation
* @param source
* @param dialog
*/
@Override
public void onNavigation(QName source, QName dialog) {
System.out.println("absolute navigation " + source + ">" + dialog);
}
class DialogWrapper {
Dialog dialog;
InteractionCoordinator coordinator;
Dialog getDialog() {
return dialog;
}
void setDialog(Dialog dialog) {
this.dialog = dialog;
}
InteractionCoordinator getCoordinator() {
return coordinator;
}
void setCoordinator(InteractionCoordinator coordinator) {
this.coordinator = coordinator;
}
}
public void reify(final String name, final AsyncCallback<Widget> callback) {
// passivate current instance before switching
if(getActiveCoordinator()!=null)
passivate();
activeDialog = name;
if (null == cachedWidgets.get(name) || this.enableCache == false)
{
Function<DialogWrapper> retrieveDialogDescription = new Function<DialogWrapper>() {
@Override
public void execute(final Control<DialogWrapper> control) {
// fetch dialog meta data
repository.getDialog(name, new SimpleCallback<Dialog>() {
@Override
public void onFailure(Throwable caught) {
super.onFailure(caught);
control.abort();
}
@Override
public void onSuccess(Dialog result) {
control.getContext().setDialog(result);
// create coordinator instance
final InteractionCoordinator coordinator = new InteractionCoordinator(
result, globalContext, Kernel.this
);
control.getContext().setCoordinator(coordinator);
control.proceed();
}
});
}
};
Outcome<DialogWrapper> delegateOutcome = new Outcome<DialogWrapper>() {
@Override
public void onFailure(DialogWrapper context) {
Console.error("Failed to retrieve dialog description: "+name);
}
@Override
public void onSuccess(DialogWrapper context) {
doReification(name, context.getDialog(), context.getCoordinator(), callback);
}
};
// step 1
DialogWrapper setup = new DialogWrapper();
new Async<DialogWrapper>().waterfall(setup, delegateOutcome, retrieveDialogDescription);
}
else
{
callback.onSuccess(cachedWidgets.get(name).asWidget());
}
}
private void doReification(
final String name,
final Dialog dialog, final InteractionCoordinator coordinator,
final AsyncCallback<Widget> widgetCallback)
{
// cache coordinator
coordinators.put(name, coordinator);
// top level interaction unit & context
final Context context = new Context();
// build reification pipeline
Function<Context> prepareContext = new Function<Context>() {
@Override
public void execute(Control<Context> control) {
context.set(ContextKey.EVENTBUS, coordinator.getLocalBus());
context.set(ContextKey.COORDINATOR, coordinator);
context.set(ContextKey.SECURITY_CONTEXT, framework.getSecurityFramework());
control.proceed();
}
};
Function<Context> readOperationMetaData = new Function<Context>() {
@Override
public void execute(final Control<Context> control) {
ReadOperationDescriptions operationMetaData = new ReadOperationDescriptions(framework.getDispatcher());
operationMetaData.prepareAsync(dialog, context, new ReificationBootstrap.Callback()
{
@Override
public void onError(Throwable caught) {
Log.error("ReadOperationDescriptions failed: " + caught.getMessage(), caught);
//progress.getBar().setProgress(25.0);
control.abort();
}
@Override
public void onSuccess() {
Log.info("Successfully retrieved operation meta data");
//progress.getBar().setProgress(25.0);
control.proceed();
}
});
}
};
Function<Context> createSecurityContext = new Function<Context>() {
@Override
public void execute(final Control<Context> control) {
SecurityFramework securityFramework = framework.getSecurityFramework();
RequiredResources resourceVisitor = new RequiredResources();
dialog.getInterfaceModel().accept(resourceVisitor);
securityFramework.createSecurityContext(activeDialog, resourceVisitor.getRequiredresources(), false,
new AsyncCallback<SecurityContext>() {
@Override
public void onFailure(Throwable caught) {
Console.error("Failed to create security context", caught.getMessage());
//progress.getBar().setProgress(50.0);
control.abort();
}
@Override
public void onSuccess(SecurityContext result) {
control.getContext().set(ContextKey.SECURITY_CONTEXT, result);
//progress.getBar().setProgress(50.0);
control.proceed();
}
}
);
}
};
Function<Context> readResourceMetaData = new Function<Context>() {
@Override
public void execute(final Control<Context> control) {
ReificationBootstrap readResourceDescription = new ReadResourceDescription(framework.getDispatcher());
readResourceDescription.prepareAsync(dialog, context, new ReificationBootstrap.Callback()
{
@Override
public void onSuccess()
{
Log.info("Successfully retrieved resource meta data");
// setup & start the reification pipeline
ReificationPipeline pipeline = new ReificationPipeline(
new UniqueIdCheckStep(),
new BuildUserInterfaceStep(),
new ImplicitBehaviourStep(framework.getDispatcher()),
new IntegrityStep());
try {
pipeline.execute(dialog, context);
//progress.getBar().setProgress(100.0);
control.proceed();
} catch (Throwable e) {
Console.error("Reification failed: "+ e.getMessage());
control.abort();
}
}
@Override
public void onError(final Throwable caught)
{
Log.error("ReadResourceDescription failed: " + caught.getMessage(), caught);
//progress.getBar().setProgress(100.0);
control.abort();
}
});
}
};
Outcome<Context> outcome = new Outcome<Context>() {
@Override
public void onFailure(final Context context) {
//progress.hide();
Window.alert("Reification failed");
}
@Override
public void onSuccess(final Context context) {
//progress.hide();
// show result
ReificationWidget widget = context.get(ContextKey.WIDGET);
assert widget !=null;
cachedWidgets.put(name, widget);
BranchActivation activation = new BranchActivation();
dialog.getInterfaceModel().accept(activation);
//System.out.println("<< Default Activation: "+activation.getCandidate()+">>");
widgetCallback.onSuccess(widget.asWidget());
}
};
// execute pipeline
//progress.center();
//progress.getBar().setProgress(25.0);
new Async<Context>(Footer.PROGRESS_ELEMENT).waterfall(context, outcome,
prepareContext, readOperationMetaData, createSecurityContext, readResourceMetaData
);
}
public void activate() {
assert activeDialog != null : "Active dialog required";
getActiveCoordinator().activate();
}
public void reset() {
assert activeDialog != null : "Active dialog required";
getActiveCoordinator().reset();
}
private KernelContract getActiveCoordinator() {
return coordinators.get(activeDialog);
}
public void passivate() {
getActiveCoordinator().passivate();
}
public void setCaching(boolean enableCache) {
this.enableCache = enableCache;
cachedWidgets.clear();
coordinators.clear();
}
}