use of com.servoy.j2db.server.ngclient.property.types.DataproviderTypeSabloValue in project servoy-client by Servoy.
the class DataAdapterList method pushChanges.
public void pushChanges(WebFormComponent webComponent, String beanProperty, Object value, String foundsetLinkedRowID) {
// TODO should this all (svy-apply/push) move to DataProviderType client/server side implementation instead of these specialized calls, instanceof checks and string parsing (see getProperty or getPropertyDescription)?
String dataProviderID = getDataProviderID(webComponent, beanProperty);
if (dataProviderID == null) {
Debug.log("apply called on a property that is not bound to a dataprovider: " + beanProperty + ", value: " + value + " of component: " + webComponent);
return;
}
Object newValue = value;
// Check security
webComponent.checkPropertyProtection(beanProperty);
IRecordInternal editingRecord = record;
if (newValue instanceof FoundsetLinkedTypeSabloValue) {
if (foundsetLinkedRowID != null) {
// find the row of the foundset that changed; we can't use client's index (as server-side indexes might have changed meanwhile on server); so we are doing it based on client sent rowID
editingRecord = getFoundsetLinkedRecord((FoundsetLinkedTypeSabloValue<?, ?>) newValue, foundsetLinkedRowID);
if (editingRecord == null) {
Debug.error("Error pushing data from client to server for foundset linked DP (cannot find record): dp=" + newValue + ", rowID=" + foundsetLinkedRowID);
return;
}
}
// hmm, this is strange - usually we should always get rowID, even if foundset linked is actually set by developer to a global or form variable - even though there rowID is not actually needed; just treat this as if it is not record linked
newValue = ((FoundsetLinkedTypeSabloValue) newValue).getWrappedValue();
}
if (newValue instanceof DataproviderTypeSabloValue)
newValue = ((DataproviderTypeSabloValue) newValue).getValue();
if (editingRecord == null || editingRecord.startEditing() || editingRecord.getParentFoundSet().getColumnIndex(dataProviderID) == -1) {
Object v;
// will update property with "image_data", property_filename with "pic.jpg" and property_mimetype with "image/jpeg"
if (newValue instanceof HashMap) {
// defining value
v = ((HashMap<?, ?>) newValue).get("");
Iterator<Entry<?, ?>> newValueIte = ((HashMap) newValue).entrySet().iterator();
while (newValueIte.hasNext()) {
Entry<?, ?> e = newValueIte.next();
if (!"".equals(e.getKey())) {
try {
com.servoy.j2db.dataprocessing.DataAdapterList.setValueObject(editingRecord, formController.getFormScope(), dataProviderID + e.getKey(), e.getValue());
} catch (IllegalArgumentException ex) {
Debug.trace(ex);
getApplication().handleException(null, new ApplicationException(ServoyException.INVALID_INPUT, ex));
}
}
}
} else {
v = newValue;
}
Object oldValue = null;
Exception setValueException = null;
try {
oldValue = com.servoy.j2db.dataprocessing.DataAdapterList.setValueObject(editingRecord, formController.getFormScope(), dataProviderID, v);
if (value instanceof DataproviderTypeSabloValue)
((DataproviderTypeSabloValue) value).checkValueForChanges(editingRecord);
} catch (IllegalArgumentException e) {
Debug.trace(e);
getApplication().handleException(null, new ApplicationException(ServoyException.INVALID_INPUT, e));
setValueException = e;
webComponent.setInvalidState(true);
}
DataproviderConfig dataproviderConfig = getDataproviderConfig(webComponent, beanProperty);
String onDataChange = dataproviderConfig.getOnDataChange();
if (onDataChange != null) {
JSONObject event = EventExecutor.createEvent(onDataChange, editingRecord.getParentFoundSet().getSelectedIndex());
event.put("data", createDataproviderInfo(editingRecord, formController.getFormScope(), dataProviderID));
Object returnValue = null;
Exception exception = null;
String onDataChangeCallback = null;
if (!Utils.equalObjects(oldValue, v) && setValueException == null && webComponent.hasEvent(onDataChange)) {
// $NON-NLS-1$ //$NON-NLS-2$
getApplication().getWebsocketSession().getClientService("$sabloLoadingIndicator").executeAsyncNowServiceCall("showLoading", null);
try {
returnValue = webComponent.executeEvent(onDataChange, new Object[] { oldValue, v, event });
} catch (Exception e) {
Debug.error("Error during onDataChange webComponent=" + webComponent, e);
exception = e;
} finally {
// $NON-NLS-1$ //$NON-NLS-2$
getApplication().getWebsocketSession().getClientService("$sabloLoadingIndicator").executeAsyncNowServiceCall("hideLoading", null);
}
onDataChangeCallback = dataproviderConfig.getOnDataChangeCallback();
} else if (setValueException != null) {
returnValue = setValueException.getMessage();
exception = setValueException;
onDataChangeCallback = dataproviderConfig.getOnDataChangeCallback();
} else if (webComponent.isInvalidState() && exception == null) {
onDataChangeCallback = dataproviderConfig.getOnDataChangeCallback();
webComponent.setInvalidState(false);
}
if (onDataChangeCallback != null) {
WebObjectFunctionDefinition call = createWebObjectFunction(onDataChangeCallback);
webComponent.invokeApi(call, new Object[] { event, returnValue, exception == null ? null : exception.getMessage() });
}
}
}
}
use of com.servoy.j2db.server.ngclient.property.types.DataproviderTypeSabloValue in project servoy-client by Servoy.
the class FoundsetLinkedTypeSabloValue method browserUpdatesReceived.
public void browserUpdatesReceived(Object newJSONValue, PropertyDescription wrappedPropertyDescription, PropertyDescription pd, IBrowserConverterContext dataConverterContext, ValueReference<Boolean> returnValueAdjustedIncommingValue) {
PushToServerEnum pushToServer = BrowserConverterContext.getPushToServerValue(dataConverterContext);
if (!wrappedValueInitialized) {
Debug.error("Trying to update state for an uninitialized foundset linked property: " + wrappedPropertyDescription + " | " + webObjectContext);
return;
}
if (!(newJSONValue instanceof JSONArray)) {
// is a data push
if (wrappedSabloValue instanceof DataproviderTypeSabloValue) {
((DataproviderTypeSabloValue) wrappedSabloValue).browserUpdateReceived(newJSONValue, dataConverterContext);
}
return;
}
if ((wrappedPropertyDescription instanceof IPushToServerSpecialType && ((IPushToServerSpecialType) wrappedPropertyDescription).shouldAlwaysAllowIncommingJSON()) || PushToServerEnum.allow.compareTo(pushToServer) <= 0) {
try {
JSONArray updates = (JSONArray) newJSONValue;
for (int i = 0; i < updates.length(); i++) {
JSONObject update = (JSONObject) updates.get(i);
if (update.has(PROPERTY_CHANGE)) {
if (viewPortChangeMonitor != null) {
Debug.error("Trying to update single state value for a foundset linked record dependent property: " + wrappedPropertyDescription + " | " + webObjectContext);
return;
}
Object object = update.get(PROPERTY_CHANGE);
YT newWrappedValue = (YT) JSONUtils.fromJSONUnwrapped(wrappedSabloValue, object, wrappedPropertyDescription, dataConverterContext, returnValueAdjustedIncommingValue);
if (newWrappedValue != wrappedSabloValue) {
// TODO should we make current method return a completely new instance instead and leave component code do the rest?
if (wrappedSabloValue instanceof IDataLinkedPropertyValue)
((IDataLinkedPropertyValue) wrappedSabloValue).detach();
setWrappedSabloValue(newWrappedValue);
if (wrappedSabloValue instanceof IDataLinkedPropertyValue)
((IDataLinkedPropertyValue) wrappedSabloValue).attachToBaseObject(changeMonitor, wrappedComponentContext);
}
} else if (update.has(ViewportDataChangeMonitor.VIEWPORT_CHANGED)) {
if (viewPortChangeMonitor == null) {
Debug.error("Trying to update some record value for a foundset linked non-record dependent property: " + wrappedPropertyDescription + " | " + webObjectContext);
return;
}
// property is linked to a foundset and the value of a property that depends on the record changed client side;
// in this case update DataAdapterList with the correct record and then set the value on the wrapped property
FoundsetTypeSabloValue foundsetPropertyValue = getFoundsetValue();
if (foundsetPropertyValue != null && foundsetPropertyValue.getFoundset() != null) {
JSONObject change = update.getJSONObject(ViewportDataChangeMonitor.VIEWPORT_CHANGED);
String rowIDValue = change.getString(FoundsetTypeSabloValue.ROW_ID_COL_KEY);
Object value = change.get(FoundsetTypeSabloValue.VALUE_KEY);
updatePropertyValueForRecord(foundsetPropertyValue, rowIDValue, value, wrappedPropertyDescription, dataConverterContext);
} else {
Debug.error("Component updates received for record linked property, but component is not linked to a foundset: " + update.get(ViewportDataChangeMonitor.VIEWPORT_CHANGED));
}
}
// as svyApply/data push for DPs does not go through here but through NGFormServiceHandler.executeMethod(String, JSONObject), the
// "setApplyingDPValueFromClient" will be called from there not here...
}
} catch (Exception ex) {
Debug.error(ex);
}
} else {
Debug.error("Foundset linked property (" + pd + ") that doesn't define a suitable pushToServer value (allow/shallow/deep) tried to update proxied value(s) serverside. Denying and sending back server value!");
if (viewPortChangeMonitor != null)
viewPortChangeMonitor.shouldSendWholeViewport();
else
changeMonitor.valueChanged();
}
}
Aggregations