Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.sf.gluebooster.java.booster.basic.mvc.Layer Maven / Gradle / Ivy
Go to download
Basic classes to support the development of applications. There should be as few dependencies on other frameworks as possible.
package net.sf.gluebooster.java.booster.basic.mvc;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import net.sf.gluebooster.java.booster.basic.transformation.CallableByCalling;
import net.sf.gluebooster.java.booster.basic.transformation.CallableByCopying;
import net.sf.gluebooster.java.booster.basic.transformation.CallableBySelecting;
import net.sf.gluebooster.java.booster.basic.transformation.CallableChain;
import net.sf.gluebooster.java.booster.basic.transformation.CallableContainerFactory;
import net.sf.gluebooster.java.booster.essentials.eventsCommands.Callable;
import net.sf.gluebooster.java.booster.essentials.eventsCommands.CallableAbstraction;
import net.sf.gluebooster.java.booster.essentials.eventsCommands.CallableByConstant;
import net.sf.gluebooster.java.booster.essentials.eventsCommands.CallableByReflection;
import net.sf.gluebooster.java.booster.essentials.eventsCommands.MultiListener;
import net.sf.gluebooster.java.booster.essentials.meta.objects.ObjectAttributes;
import net.sf.gluebooster.java.booster.essentials.utils.Check;
import net.sf.gluebooster.java.booster.essentials.utils.Constants;
import net.sf.gluebooster.java.booster.essentials.utils.ContainerBoostUtils;
import net.sf.gluebooster.java.booster.essentials.utils.ReflectionBoostUtils;
import net.sf.gluebooster.java.booster.essentials.utils.XmlBoostUtils;
/**
* A layer of a multitier architecture. A layer may contain a model that is needed for the invocation of the next (backend) layer. Calls of a layer always
* contain the model of the previous layer.
*
* Example: Display Layer: Swing, JavaFX, JSF Beans for html View Layer: User 1, User 2 Backend Layer: Business Logic
*
* @defaultParamText name the name of the instance
*
* @author cbauer
*
*/
public class Layer extends CallableAbstraction {
/**
* The backend layer. Example: The backend of a view is a controller; the backend of a display is a view
*/
private Layer backend;
/**
* The model with which the next (backend) layer is called and (after the call) which values are processed (e.g. displayed).
*/
private Map modelOfBackendLayer;
/**
* May be used when this layer has an own model, independent of the models that are propagated during the calls. Example: The number of logged in persons
*/
private Map modelOfThisLayer;
/**
* Commands to be executed. The preferable result of the callable is Boolean (success = true, failure = false). If no Boolean is returned, then success is
* assumed.
*/
private Map callablePerCommand = new HashMap();
public Map getModelOfBackendLayer() {
if (modelOfBackendLayer == null) {
modelOfBackendLayer = new ObjectAttributes("backendmodel of " + getName());
}
return modelOfBackendLayer;
}
public void setModelOfBackendLayer(Map modelOfNextLayer) {
this.modelOfBackendLayer = modelOfNextLayer;
}
public Layer(String name) throws Exception {
this(name, null);
}
/**
*
* @param modelOfNextLayer
* the model of the backend layer
*/
public Layer(String name, Map modelOfNextLayer) throws Exception {
super(name);
this.modelOfBackendLayer = modelOfNextLayer;
// default setting: nothing MUST be done at start
}
/**
* Declares that this layer must do nothing to start.
*
* @throws Exception
*
*/
public void noStartNecessary() throws Exception {
setCommandCallable(Constants.START, new CallableByConstant("no start sequence"));
}
/**
* Declares that this layer must do nothing when stopping
*
* @throws Exception
*
*/
public void noStopNecessary() throws Exception {
setCommandCallable(Constants.STOP, new CallableByConstant("no stop sequence"));
}
public Map getModelOfThisLayer() {
if (modelOfThisLayer == null) {
modelOfThisLayer = new ObjectAttributes("model of " + getName());
}
return modelOfThisLayer;
}
public void setModelOfThisLayer(Map modelOfThisLayer) {
this.modelOfThisLayer = modelOfThisLayer;
}
/**
* Connects a command with a callable
*
* @param command
* the command which should invoke the callable
* @param callable
* parameters are command, commandParameters, map model
* @throws Exception
*/
public void setCommandCallable(Object command, Callable callable) throws Exception {
// if the callable returns no boolean true is returned
// Condition postcondition = callable.getPostcondition();
// Collection isBoolean = postcondition.implies(new ValueDescription<>(Boolean.class));
// if (isBoolean != null && !isBoolean.isEmpty()) {
// throw new IllegalStateException("result must be Boolean, but is " + postcondition);
// }
callablePerCommand.put(command, callable);
}
/**
* Sets the callable that is invoked when starting/stopping.
*
* @param listener
* parameters are command (Constants.START/STOP), commandParameters, map model
* @throws Exception
*/
public void setStartStopCallable(Callable listener) throws Exception {
setCommandCallable(Constants.START, listener);// start repeater
setCommandCallable(Constants.STOP, listener);// stop repeater
}
public Map getCallablePerCommand() {
return callablePerCommand;
}
public void setCallablePerCommand(Map callablePerCommand) {
this.callablePerCommand = callablePerCommand;
}
/**
* @param parameters
* command name, command parameters, model map
* @return model map
*/
@Override
protected final Map callImpl(Object... parameters) throws Exception {
Object commandName = null;
Object commandParameters = null;
Map model = null;
if (parameters != null) {
int size = parameters.length;
if (size > 0) {
commandName = parameters[0];
}
if (size > 1) {
commandParameters = parameters[1];
}
if (size > 2) {
model = (Map) parameters[2];
}
}
Object partResult = null;
if (callablePerCommand.containsKey(commandName)) {
Callable callable = callablePerCommand.get(commandName);
partResult = callable.call(commandName, commandParameters, model);
} else if (!exec(commandName, commandParameters, model)) {
throw new IllegalStateException("command " + commandName + " not supported by " + this + " (" + getClass().getSimpleName() + ")");
}
return model;
}
/**
* Selects the model (if the call parameters are "command" (ignored), "commandParameters" (ignored), model).
*
* @return the created callable that selects the model
*/
public Callable selectModel() {
return new CallableBySelecting("select model. ", 2);// TODO precondition arraysize
}
/**
* Selects the parameters (if the call parameters are "command" (ignored), "commandParameters", model (ignored)).
*
* @return the created callable that selects the parameters
*/
public Callable selectParameters() {
return new CallableBySelecting("select parameters ", 1);// TODO precondition arraysize
}
/**
* Selects the command (if the call parameters are "command" , "commandParameters" (ignored), model (ignored)).
*
* @return the created callable that selects the command
*/
public Callable selectCommand() {
return new CallableBySelecting("select command", 0);
}
/**
* Selects the model (if the call parameters are "command" (ignored), "commandParameters" (ignored), model). See ContainerBoostUtils.putIntoMap to put a
* value into the model.
*
* @param key
* the key of the field
* @return the created callable that selects the field of the model
*/
public CallableAbstraction selectModelField(Object key) {
return new CallableChain("select model field '" + key + "'", selectModel(), new CallableBySelecting("select original text", key));
}
/**
* Implementation of the command execution. Must be overwritten or the setCommand-Method must be used.
*
* @param commandName
* the name of the command.
* @param parameter
* the parameter of the command
* @param model
* the current model. It may be modified during execution
* @return true if the command has been fully handled
*/
protected boolean exec(Object commandName, Object parameter, Map model) throws Exception {
return false;
}
public Layer getBackend() {
return backend;
}
public void setBackend(Layer backend) {
this.backend = backend;
}
/**
* Create an action listener that extracts the command from the action and calls this (without model).
*
* @return the created listener
*/
public ActionListener createActionListener(/* Map model */) throws Exception {
return new MultiListener(new CallableChain("invoke event command on view",
// "actionPerformed", actionEvent
new CallableContainerFactory("extract event", Constants.ARRAY, new int[] { 1 }),
// actionEvent
new CallableByReflection("extract command", null, ActionEvent.class.getMethod(Constants.GETACTIONCOMMAND)),
// command
new CallableByCalling("call " + this, this, new Object[] { null, null, null/* model */ }, new int[] { 0 })
// executes this.call(command, null, null /* model*/)
));
}
/**
* Create a callable to which commands are passed
*
* @param backend
* will receive the calls
* @param useModelOfBackendLayer
* should the model of the backend layer be used as command parameter
* @return the created callable
*/
public CallableAbstraction passTo(Callable backend, boolean useModelOfBackendLayer) throws Exception {
Map backendModel = useModelOfBackendLayer ? getModelOfBackendLayer() : null;
return new CallableByCalling("pass to backend layer", backend, new Object[] { null, null, backendModel });
}
/**
* Execute a command by the controller.
*
* @param command
* the command to be invoked
* @param parameter
* parameter of the command
* @return the result of the command
*/
protected Map callBackend(Object command, Object... parameter) throws Exception {
return getBackend().call(command, parameter, getModelOfBackendLayer());
}
/**
* If the parameter is an object array with only 1 element, it returns the element. Otherwise the parameter is returned.
*
* @param parameter
* will be inspected
* @return parameter or parameter[0]
*/
protected Result getSingleParameter(Object parameter) {
if (parameter != null && parameter.getClass().isArray() && Array.getLength(parameter) == 1) {
return (Result) Array.get(parameter, 0);
} else {
return (Result) parameter;
}
}
/**
* Creates a callable that calls this instance with a given command and parameters
*
* @param command
* the command
* @param parameters
* parameters of the command
* @param model
* model to be used
* @return the created callable
*/
public CallableAbstraction createExecuteCommandCallable(Object command, Object parameters, Map model) throws Exception {
Object name = getName();
if (name == null) {
name = "";
}
Object commandName = "";
if (command != null && !Constants.REPLACE.equals(command)) {
commandName = command + " ";
}
return new CallableByReflection("invoke " + commandName + "on the controller " + name, this,
ReflectionBoostUtils.getMethod(Callable.class, Constants.CALL), command, parameters, model);
}
/**
* Creates a callable that passes the command and its parameters to this instance
*
* @param model
* used as command parameter
* @return the created callable
*/
public CallableAbstraction passCommand(Map model) throws Exception {
return createExecuteCommandCallable(Constants.REPLACE, null, model);// replace the first parameter with the actual command
}
/**
* Copies some entries from the backend model into another model (example: frontend model)
*
* @param otherModel
* will be modified
* @param keys
* the keys of the entries
*/
protected final void copyBackendModelTo(Map otherModel, Collection keys) throws Exception {
Map controllerModel = getModelOfBackendLayer();
ContainerBoostUtils.copy(controllerModel, otherModel, keys, true);
}
/**
* Copies some entries from the backend model to another model
*
* @param otherModel
* will be modified
* @param keys
* the keys of the entries
*/
protected final void copyBackendModelTo(Map otherModel, Object... keys) throws Exception {
Map controllerModel = getModelOfBackendLayer();
ContainerBoostUtils.copyVararg(controllerModel, otherModel, true, keys);
}
/**
* Create a callable that copies some field into another model. The argument of call is the source model from which the values are copied.
*
* @param targetModel
* will be modified
* @param fieldNames
* the names of the fields that will be copied.
* @return the created callable
*/
public static Callable copyIntoModel(Map targetModel, Object... fieldNames) {
return new CallableByCopying("copyIntoDisplayModel", null, targetModel, fieldNames);
}
/**
* Lets the backend execute a command with some fields as parameters (map)
*
* @param command
* the command to be executed
* @param fieldnames
* the names of the fields to be transferred (as map) to the controller
* @param allFields
* some fields will be selected
* @return the result of the command
*/
protected final Map backendCommandWithFields(Object command, Collection fieldnames, Map allFields) throws Exception {
Map selectedFields = new HashMap();
ContainerBoostUtils.copy(allFields, selectedFields, fieldnames, true);
return callBackend(command, selectedFields);
}
/**
* Creates a callable that expects (command, File as parameter, model) and serializes an field of the model into the file denoted by the parameter (format:
* UTF-8 xml)
*
* @param callableName
* name of the result
* @param modelKey
* the field to be serialized
* @return the created callable
*/
public final CallableAbstraction serializeModelField(String callableName, Object modelKey) throws Exception {
// save cards
Callable createOutputStream = new CallableChain("create output stream for " + callableName, selectParameters(),
new CallableByReflection("FileOutputStream constructor", FileOutputStream.class.getConstructor(File.class)));
Callable getFlashcards = selectModelField(modelKey);
CallableByCalling parameters = new CallableByCalling<>("parameters for writeAsUtf8Xml", new Object[] { getFlashcards, createOutputStream, true, 0 });
CallableChain result = new CallableChain<>(callableName, parameters, XmlBoostUtils.writeAsUtf8XmlCallable("writer of " + callableName));
// TODO put feedback into model
return result;
}
/**
* Creates a callable that expects (command, File as parameter, model) and deserializes an field of the model from the the file denoted by the parameter
* (format: UTF-8 xml)
*
* @param callableName
* the name of the result
* @param modelKey
* the name of the field
* @return the created callable
*/
public final CallableAbstraction deserializeIntoModelField(String callableName, Object modelKey) throws Exception {
// save cards
CallableAbstraction createStream = new CallableChain("create input stream for " + callableName, selectParameters(),
new CallableByReflection("FileInputStream constructor", FileInputStream.class.getConstructor(File.class))
, XmlBoostUtils.readFromUtf8XmlCallable("deserialize " + callableName), Check.notNullChecker("deserialized " + modelKey));
createStream.setBreakpoint();
CallableAbstraction parameters = new CallableByCalling<>("create [model,inputstream] ", new Object[] { selectModel(), createStream });
// parameters.setBreakpoint();
CallableChain result = new CallableChain<>(callableName, parameters, ContainerBoostUtils.putIntoMap("put " + modelKey + " into model", modelKey));
return result;
}
}