Search in sources :

Example 1 with DataproviderTypeSabloValue

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() });
            }
        }
    }
}
Also used : IRecordInternal(com.servoy.j2db.dataprocessing.IRecordInternal) HashMap(java.util.HashMap) WeakHashMap(java.util.WeakHashMap) WebObjectFunctionDefinition(org.sablo.specification.WebObjectFunctionDefinition) FoundsetLinkedTypeSabloValue(com.servoy.j2db.server.ngclient.property.FoundsetLinkedTypeSabloValue) JSONException(org.json.JSONException) ApplicationException(com.servoy.j2db.ApplicationException) IllegalChangeFromClientException(org.sablo.IllegalChangeFromClientException) ServoyException(com.servoy.j2db.util.ServoyException) RepositoryException(com.servoy.j2db.persistence.RepositoryException) Entry(java.util.Map.Entry) ApplicationException(com.servoy.j2db.ApplicationException) JSONObject(org.json.JSONObject) ServoyJSONObject(com.servoy.j2db.util.ServoyJSONObject) DataproviderTypeSabloValue(com.servoy.j2db.server.ngclient.property.types.DataproviderTypeSabloValue) JSONObject(org.json.JSONObject) BaseWebObject(org.sablo.BaseWebObject) ServoyJSONObject(com.servoy.j2db.util.ServoyJSONObject) DataproviderConfig(com.servoy.j2db.server.ngclient.property.DataproviderConfig)

Example 2 with DataproviderTypeSabloValue

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();
    }
}
Also used : JSONObject(org.json.JSONObject) DataproviderTypeSabloValue(com.servoy.j2db.server.ngclient.property.types.DataproviderTypeSabloValue) IPushToServerSpecialType(org.sablo.specification.property.IPushToServerSpecialType) JSONArray(org.json.JSONArray) JSONObject(org.json.JSONObject) PushToServerEnum(org.sablo.specification.WebObjectSpecification.PushToServerEnum) JSONException(org.json.JSONException)

Aggregations

DataproviderTypeSabloValue (com.servoy.j2db.server.ngclient.property.types.DataproviderTypeSabloValue)2 JSONException (org.json.JSONException)2 JSONObject (org.json.JSONObject)2 ApplicationException (com.servoy.j2db.ApplicationException)1 IRecordInternal (com.servoy.j2db.dataprocessing.IRecordInternal)1 RepositoryException (com.servoy.j2db.persistence.RepositoryException)1 DataproviderConfig (com.servoy.j2db.server.ngclient.property.DataproviderConfig)1 FoundsetLinkedTypeSabloValue (com.servoy.j2db.server.ngclient.property.FoundsetLinkedTypeSabloValue)1 ServoyException (com.servoy.j2db.util.ServoyException)1 ServoyJSONObject (com.servoy.j2db.util.ServoyJSONObject)1 HashMap (java.util.HashMap)1 Entry (java.util.Map.Entry)1 WeakHashMap (java.util.WeakHashMap)1 JSONArray (org.json.JSONArray)1 BaseWebObject (org.sablo.BaseWebObject)1 IllegalChangeFromClientException (org.sablo.IllegalChangeFromClientException)1 WebObjectFunctionDefinition (org.sablo.specification.WebObjectFunctionDefinition)1 PushToServerEnum (org.sablo.specification.WebObjectSpecification.PushToServerEnum)1 IPushToServerSpecialType (org.sablo.specification.property.IPushToServerSpecialType)1