package org.swingml.event;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import org.swingml.*;
import org.swingml.event.*;
import org.swingml.model.*;
import org.swingml.registry.*;
import org.swingml.server.SwingMLServerResponse;
import org.swingml.system.*;
/**
* @author David Pitt
* This event handler invokes a URL address with specified key value parameter pairs.
* Response XML is rendered in a specified SwingML container.
*
* Parameters
*
* OPEN = <OPEN|OPEN-MODEL|REFRESH|NORENDER>
* COMPONENT = <Container Name>
* URL = URL to post specified param values and container component Name Value pairs
* if not specified, the URL property defined in the SwingMLProperties object will be used
*
*
*
*/
public class ControllerActionEventHandler extends EventUtil {
private Component component;
private String panel;
private Map actionParameters;
private Container parent;
private ControllerActionModel model = null;
public ControllerActionEventHandler () {}
public ControllerActionEventHandler (Component aComponent, Map aMap) {
setActionParameters(aMap);
setComponent(aComponent);
if (aComponent instanceof Container) {
setParent((Container) aComponent);
}
}
public void destroy () {}
protected ActionParamModel getActionParamModel (String key) {
ActionParamModel result = null;
Object value = getActionParameters().get(key);
if (value != null) {
result = (ActionParamModel) value;
}
return result;
}
public Component getComponent () {
return this.component;
}
private String getEventSource () {
return "&" + Constants.EVENT_SOURCE + "=" + getParameterValue(Constants.EVENT_SOURCE);
}
private String getModalParameterString () {
StringBuffer ps = new StringBuffer();
Iterator keys = getActionParameters().keySet().iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
if (!"EVENT-SOURCE".equals(key)) {
ps.append(key);
ps.append("=");
ps.append(getParameterValue(key));
ps.append("&");
}
}
return ps.toString();
}
protected String getPanel () {
return this.panel;
}
protected String getParameterValue (String key) {
String result = null;
if (getActionParameters() == null) { return result; }
Object value = getActionParameters().get(key);
if (value != null) {
result = ((ActionParamModel) value).getValue();
}
return result;
}
protected Map getActionParameters () {
return this.actionParameters;
}
protected String getParameterString () {
StringBuffer ps = new StringBuffer();
if (getActionParameters() == null) {return "";}
Iterator keys = getActionParameters().keySet().iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
ps.append(key);
ps.append("=");
ps.append(getParameterValue(key));
if (keys.hasNext()) {
ps.append("&");
}
}
return ps.toString();
}
public Container getParent () {
return this.parent;
}
/**
* This method expects the objects in the params argument to be instances of
* the ActionParamModel object. And will replace tokendized map values with values
* looked up from the SwingMLProperties singleton. If a tokenized key is not found, and error
* is reported
*
* @param params
* A reference to an array of Object instances.
*
*
*
* @return void
* @see com.crosslogic.swingml.model.ActionParamModel
*/
protected void replaceTokens (Object[] aParams) {
ActionParamModel theParam = null;
if (aParams != null && aParams.length > 0) {
for (int i = 0; i < aParams.length; i++) {
if (aParams[i] instanceof ActionParamModel) {
theParam = (ActionParamModel) aParams[i];
int index = 0;
if ( (index = theParam.getValue().indexOf("@")) > -1) {
String key = theParam.getValue().substring(index+1);
String replaceWith = SwingMLProperties.sole().get(key);
if (replaceWith == null) {
throw new RuntimeException("Token "+theParam.getValue()+" not found in SwingMLProperties instance, make sure it has been initialized somewhere..." );
}
// replace with new looked up value
theParam.setValue(replaceWith);
}
}
}
}
return;
}
public void initialize (Component aComponent, Object[] parameters,ControllerActionModel model) {
setModel(model);
replaceTokens(parameters);
setActionParameters(buildActionParametersMap(parameters));
setComponent(aComponent);
if (aComponent instanceof Container) {
setParent((Container) aComponent);
}
}
public void invoke () {
try {
// setPanel(getParameterValue(Constants.OPEN_MODAL));
if (getModel().getOperation().equalsIgnoreCase(Constants.OPEN) ) {
open(parent,
getParameterString(), shouldShowProgress());
} else if (getModel().getOperation().equalsIgnoreCase(Constants.REFRESH)){
refresh(parent,
getParameterString());
} else if (getModel().getOperation().equalsIgnoreCase(Constants.NORENDER)) {
noRender(parent,getParameterString());
}
} catch (InvalidTargetLocationException e) {
// tried to connect to an invalid location
// log the error
SwingMLLogger.getInstance().log(SwingMLLogger.ERROR, e);
// notify the user
SwingMLRenderer.getRenderer().render(HttpSubmitController.getInvalidTargetErrorSpec(), null);
}
}
public void setComponent (Component component) {
this.component = component;
}
protected void setPanel (String panel) {
this.panel = panel;
}
protected void setActionParameters (Map params) {
this.actionParameters = params;
}
public void setParent (Container parentContainer) {
this.parent = parentContainer;
}
/**
* Looks for the INDICATE-PROGRESS parameter. If found, and equal to 'false'
* then returns FALSE, else this defaults to return TRUE.
*
* @return
*/
private boolean shouldShowProgress () {
boolean result = true;
if (getParameterValue(Constants.INDICATE_PROGRESS) != null && "false".equals((getParameterValue(Constants.INDICATE_PROGRESS)).toLowerCase())) {
result = false;
}
return result;
}
public void open(Container parentContainer, String params, boolean showProgress) {
SwingMLServerResponse response = null;
String url = null;
url = computeURL();
if (url != null) {
response = HttpSubmitController.submit(url, parentContainer, params, showProgress);
} else {
throw new InvalidTargetLocationException("Error accessing URL, make sure URL Property entry is defined...");
}
SwingMLRenderer renderer = SwingMLRenderer.getRenderer();
if (response != null) {
renderer.render(response.getSwingMLSpec(), parentContainer);
if (response.hasErrors()) {
SwingMLModel model = (SwingMLModel) SwingMLModelToContainerRegistry.getModel(parentContainer);
// TODO - Edit Substitute
model.handle(response.getErrors());
}
} else {
renderer.render(HttpSubmitController.getConnectionErrorSpec(), parentContainer);
}
}
public String computeURL() {
// if URL is specified in action parameters us this, otherwise use default.
String URL = null;
URL = getModel().getUrl();
if (URL == null) {
URL = SwingMLProperties.sole().get("URL");
}
return URL;
}
/**
* Refresh the given container.
*
* @param container
*/
public void refresh(Container container,String params) {
disableComponents(container);
String theHttpRequest = HttpSubmitController.buildHttpRequest(container);
String url = computeURL();
if (url != null) {
SwingMLServerResponse response = HttpSubmitController.submit(url, params+"&"+theHttpRequest, container);
SwingMLRenderer renderer = SwingMLRenderer.getRenderer();
if (response != null) {
renderer.processAndRender(response.getSwingMLSpec(), container, true, true);
if (response.hasErrors()) {
SwingMLModel model = (SwingMLModel) SwingMLModelToContainerRegistry.getModel(container);
model.handle(response.getErrors());
}
} else {
renderer.render(HttpSubmitController.getConnectionErrorSpec(), container);
}
} else {
throw new InvalidTargetLocationException(container.getName());
}
}
/**
* Invoke the specified URL, No result expected, therefore XML will not be rendered...
*
* @param container
*/
public void noRender(Container container,String params) {
String theHttpRequest = HttpSubmitController.buildHttpRequest(container);
String url = computeURL();
if (url != null) {
SwingMLServerResponse response = HttpSubmitController.submit(url, params+"&"+theHttpRequest, container);
} else {
throw new InvalidTargetLocationException(container.getName());
}
}
private void disableComponents (Component component) {
component.setEnabled(false);
// recurse children?
if (component instanceof Container) {
Container container = (Container) component;
Component[] children = container.getComponents();
for (int x = 0; x < children.length; x++) {
disableComponents(children[x]);
}
}
}
public ControllerActionModel getModel() {
return model;
}
public void setModel(ControllerActionModel model) {
this.model = model;
}
}