import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage;
import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize;
import com.vaadin.terminal.gwt.client.RenderInformation.Size;
+import com.vaadin.terminal.gwt.client.communication.MethodInvocation;
import com.vaadin.terminal.gwt.client.ui.Field;
import com.vaadin.terminal.gwt.client.ui.VContextMenu;
import com.vaadin.terminal.gwt.client.ui.VNotification;
private static final String ERROR_CLASSNAME_EXT = "-error";
+ public static final String UPDATE_VARIABLE_METHOD = "v";
+
public static final char VAR_RECORD_SEPARATOR = '\u001e';
public static final char VAR_FIELD_SEPARATOR = '\u001f';
private final HashMap<String, String> resourcesMap = new HashMap<String, String>();
- private final ArrayList<String> pendingVariables = new ArrayList<String>();
+ private ArrayList<MethodInvocation> pendingInvocations = new ArrayList<MethodInvocation>();
private WidgetSet widgetSet;
private ApplicationConfiguration configuration;
/** List of pending variable change bursts that must be submitted in order */
- private final ArrayList<ArrayList<String>> pendingVariableBursts = new ArrayList<ArrayList<String>>();
+ private final ArrayList<ArrayList<MethodInvocation>> pendingBursts = new ArrayList<ArrayList<MethodInvocation>>();
/** Timer for automatic refirect to SessionExpiredURL */
private Timer redirectTimer;
* change set if it exists.
*/
private void checkForPendingVariableBursts() {
- cleanVariableBurst(pendingVariables);
- if (pendingVariableBursts.size() > 0) {
- for (Iterator<ArrayList<String>> iterator = pendingVariableBursts
+ cleanVariableBurst(pendingInvocations);
+ if (pendingBursts.size() > 0) {
+ for (Iterator<ArrayList<MethodInvocation>> iterator = pendingBursts
.iterator(); iterator.hasNext();) {
cleanVariableBurst(iterator.next());
}
- ArrayList<String> nextBurst = pendingVariableBursts.get(0);
- pendingVariableBursts.remove(0);
+ ArrayList<MethodInvocation> nextBurst = pendingBursts.get(0);
+ pendingBursts.remove(0);
buildAndSendVariableBurst(nextBurst, false);
}
}
*
* @param variableBurst
*/
- private void cleanVariableBurst(ArrayList<String> variableBurst) {
- for (int i = 1; i < variableBurst.size(); i += 2) {
- String id = variableBurst.get(i);
- id = id.substring(0, id.indexOf(VAR_FIELD_SEPARATOR));
+ private void cleanVariableBurst(ArrayList<MethodInvocation> variableBurst) {
+ for (int i = 1; i < variableBurst.size(); i++) {
+ String id = variableBurst.get(i).getPaintableId();
if (!getPaintableMap().hasPaintable(id)
&& !getPaintableMap().isDragAndDropPaintable(id)) {
// variable owner does not exist anymore
- variableBurst.remove(i - 1);
- variableBurst.remove(i - 1);
- i -= 2;
+ variableBurst.remove(i);
VConsole.log("Removed variable from removed component: " + id);
}
}
private void addVariableToQueue(String paintableId, String variableName,
String encodedValue, boolean immediate, char type) {
- final String id = paintableId + VAR_FIELD_SEPARATOR + variableName
- + VAR_FIELD_SEPARATOR + type;
- for (int i = 1; i < pendingVariables.size(); i += 2) {
- if ((pendingVariables.get(i)).equals(id)) {
- pendingVariables.remove(i - 1);
- pendingVariables.remove(i - 1);
- break;
- }
- }
- pendingVariables.add(encodedValue);
- pendingVariables.add(id);
+ // TODO could eliminate invocations of same shared variable setter
+ String param = variableName + VAR_FIELD_SEPARATOR + type
+ + VAR_FIELD_SEPARATOR + encodedValue;
+ addMethodInvocationToQueue(paintableId, new MethodInvocation(
+ paintableId, UPDATE_VARIABLE_METHOD, param), immediate);
+ }
+
+ private void addMethodInvocationToQueue(String paintableId,
+ MethodInvocation invocation, boolean immediate) {
+ pendingInvocations.add(invocation);
if (immediate) {
sendPendingVariableChanges();
}
if (applicationRunning) {
if (hasActiveRequest()) {
// skip empty queues if there are pending bursts to be sent
- if (pendingVariables.size() > 0
- || pendingVariableBursts.size() == 0) {
- ArrayList<String> burst = (ArrayList<String>) pendingVariables
- .clone();
- pendingVariableBursts.add(burst);
- pendingVariables.clear();
+ if (pendingInvocations.size() > 0 || pendingBursts.size() == 0) {
+ pendingBursts.add(pendingInvocations);
+ pendingInvocations = new ArrayList<MethodInvocation>();
}
} else {
- buildAndSendVariableBurst(pendingVariables, false);
+ buildAndSendVariableBurst(pendingInvocations, false);
}
}
}
* at the same time. This is ok as we can assume that DOM will never be
* updated after this.
*
- * @param pendingVariables
- * Vector of variable changes to send
+ * @param pendingInvocations
+ * List of RPC method invocations to send
* @param forceSync
* Should we use synchronous request?
*/
- private void buildAndSendVariableBurst(ArrayList<String> pendingVariables,
- boolean forceSync) {
+ private void buildAndSendVariableBurst(
+ ArrayList<MethodInvocation> pendingInvocations, boolean forceSync) {
final StringBuffer req = new StringBuffer();
- while (!pendingVariables.isEmpty()) {
+ while (!pendingInvocations.isEmpty()) {
if (ApplicationConfiguration.isDebugMode()) {
- Util.logVariableBurst(this, pendingVariables);
+ Util.logVariableBurst(this, pendingInvocations);
}
- for (int i = 0; i < pendingVariables.size(); i++) {
+ // TODO use JSON for messages
+ for (int i = 0; i < pendingInvocations.size(); i++) {
if (i > 0) {
- if (i % 2 == 0) {
- req.append(VAR_RECORD_SEPARATOR);
- } else {
- req.append(VAR_FIELD_SEPARATOR);
- }
+ req.append(VAR_RECORD_SEPARATOR);
}
- req.append(pendingVariables.get(i));
+ MethodInvocation invocation = pendingInvocations.get(i);
+ req.append(invocation.getPaintableId());
+ req.append(VAR_FIELD_SEPARATOR);
+ req.append(invocation.getMethodName());
+ req.append(VAR_FIELD_SEPARATOR);
+ // TODO support multiple parameters
+ req.append(invocation.getParameters());
}
- pendingVariables.clear();
- // Append all the busts to this synchronous request
- if (forceSync && !pendingVariableBursts.isEmpty()) {
- pendingVariables = pendingVariableBursts.get(0);
- pendingVariableBursts.remove(0);
+ pendingInvocations.clear();
+ // Append all the bursts to this synchronous request
+ if (forceSync && !pendingBursts.isEmpty()) {
+ pendingInvocations = pendingBursts.get(0);
+ pendingBursts.remove(0);
req.append(VAR_BURST_SEPARATOR);
}
}
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize;
+import com.vaadin.terminal.gwt.client.communication.MethodInvocation;
public class Util {
return idx;
}
- private static void printPaintablesVariables(ArrayList<String[]> vars,
- String id, ApplicationConnection c) {
+ private static void printPaintablesInvocations(
+ ArrayList<MethodInvocation> invocations, String id,
+ ApplicationConnection c) {
VPaintableWidget paintable = (VPaintableWidget) VPaintableMap.get(c)
.getPaintable(id);
if (paintable != null) {
VConsole.log("\t" + id + " (" + paintable.getClass() + ") :");
- for (String[] var : vars) {
- VConsole.log("\t\t" + var[1] + " (" + var[2] + ")" + " : "
- + var[0]);
+ for (MethodInvocation invocation : invocations) {
+ String formattedParams = invocation.getParameters();
+ if (ApplicationConnection.UPDATE_VARIABLE_METHOD
+ .equals(invocation.getMethodName())) {
+ // if an updateVariable call, format as variable changes
+ // ensure with limit that also trailing parameters are
+ // included
+ String[] split = invocation
+ .getParameters()
+ .split(String
+ .valueOf(ApplicationConnection.VAR_FIELD_SEPARATOR),
+ 3);
+
+ // unless of correct length, do not reformat
+ if (split.length == 3) {
+ // TODO needs to be reworked
+ // name, type, value
+ formattedParams = split[0] + " (" + split[1] + ")"
+ + " : " + split[2];
+ }
+ }
+ VConsole.log("\t\t" + invocation.getMethodName() + "("
+ + formattedParams + ")");
}
}
}
static void logVariableBurst(ApplicationConnection c,
- ArrayList<String> loggedBurst) {
+ ArrayList<MethodInvocation> loggedBurst) {
try {
VConsole.log("Variable burst to be sent to server:");
String curId = null;
- ArrayList<String[]> vars = new ArrayList<String[]>();
+ ArrayList<MethodInvocation> invocations = new ArrayList<MethodInvocation>();
for (int i = 0; i < loggedBurst.size(); i++) {
- String value = loggedBurst.get(i++);
- String[] split = loggedBurst
- .get(i)
- .split(String
- .valueOf(ApplicationConnection.VAR_FIELD_SEPARATOR));
- String id = split[0];
+ String id = loggedBurst.get(i).getPaintableId();
if (curId == null) {
curId = id;
} else if (!curId.equals(id)) {
- printPaintablesVariables(vars, curId, c);
- vars.clear();
+ printPaintablesInvocations(invocations, curId, c);
+ invocations.clear();
curId = id;
}
- split[0] = value;
- vars.add(split);
+ invocations.add(loggedBurst.get(i));
}
- if (!vars.isEmpty()) {
- printPaintablesVariables(vars, curId, c);
+ if (!invocations.isEmpty()) {
+ printPaintablesInvocations(invocations, curId, c);
}
} catch (Exception e) {
VConsole.error(e);
private static final String WRITE_SECURITY_TOKEN_FLAG = "writeSecurityToken";
/* Variable records indexes */
- private static final int VAR_PID = 1;
- private static final int VAR_NAME = 2;
+ private static final int VAR_PID = 0;
+ private static final int VAR_METHOD = 1;
+ private static final int VAR_VARNAME = 2;
private static final int VAR_TYPE = 3;
- private static final int VAR_VALUE = 0;
+ private static final int VAR_VALUE = 4;
private static final char VTYPE_PAINTABLE = 'p';
private static final char VTYPE_BOOLEAN = 'b';
for (int bi = 1; bi < bursts.length; bi++) {
final String burst = bursts[bi];
- success = handleVariableBurst(request, application2, success,
- burst);
+ success = handleBurst(request, application2, success, burst);
// In case that there were multiple bursts, we know that this is
// a special synchronous case for closing window. Thus we are
return success;
}
- public boolean handleVariableBurst(Object source, Application app,
- boolean success, final String burst) {
+ public boolean handleBurst(Object source, Application app, boolean success,
+ final String burst) {
// extract variables to two dim string array
final String[] tmp = burst.split(String.valueOf(VAR_RECORD_SEPARATOR));
- final String[][] variableRecords = new String[tmp.length][4];
+ // TODO support variable number of parameters
+ final String[][] variableRecords = new String[tmp.length][5];
for (int i = 0; i < tmp.length; i++) {
- variableRecords[i] = tmp[i].split(String
- .valueOf(VAR_FIELD_SEPARATOR));
+ // ensure with limit that also trailing parameters are included
+ variableRecords[i] = tmp[i].split(
+ String.valueOf(VAR_FIELD_SEPARATOR), 5);
}
for (int i = 0; i < variableRecords.length; i++) {
nextVariable = variableRecords[i + 1];
}
final VariableOwner owner = getVariableOwner(variable[VAR_PID]);
+ final String methodName = variable[VAR_METHOD];
+ if (!ApplicationConnection.UPDATE_VARIABLE_METHOD
+ .equals(methodName)) {
+ // TODO handle other RPC calls
+ continue;
+ }
if (owner != null && owner.isEnabled()) {
Map<String, Object> m;
if (nextVariable != null
// we have more than one value changes in row for
// one variable owner, collect them in HashMap
m = new HashMap<String, Object>();
- m.put(variable[VAR_NAME],
+ m.put(variable[VAR_VARNAME],
convertVariableValue(variable[VAR_TYPE].charAt(0),
variable[VAR_VALUE]));
} else {
// use optimized single value map
m = Collections.singletonMap(
- variable[VAR_NAME],
+ variable[VAR_VARNAME],
convertVariableValue(variable[VAR_TYPE].charAt(0),
variable[VAR_VALUE]));
}
} else {
nextVariable = null;
}
- m.put(variable[VAR_NAME],
+ m.put(variable[VAR_VARNAME],
convertVariableValue(variable[VAR_TYPE].charAt(0),
variable[VAR_VALUE]));
}
// Handle special case where window-close is called
// after the window has been removed from the
// application or the application has closed
- if ("close".equals(variable[VAR_NAME])
+ if ("close".equals(variable[VAR_VARNAME])
&& "true".equals(variable[VAR_VALUE])) {
// Silently ignore this
continue;