Search in sources :

Example 6 with IFlexFields

use of org.jaffa.flexfields.IFlexFields in project jaffa-framework by jaffa-projects.

the class TransformerUtils method updateBeanData.

static void updateBeanData(String path, GraphDataObject source, UOW uow, ITransformationHandler handler, GraphMapping mapping, IPersistent domainObject, DataTransformer.Mode mode, GraphDataObject newGraph) throws InstantiationException, IllegalAccessException, InvocationTargetException, ApplicationExceptions, FrameworkException {
    try {
        // No need to invoke it during CLONING/MASS_UPDATE as well, since the source object should be unmodified
        if (mode != DataTransformer.Mode.VALIDATE_ONLY && mode != DataTransformer.Mode.CLONE && mode != DataTransformer.Mode.MASS_UPDATE)
            source.validate();
        List<ITransformationHandler> handlers = null;
        if (handler != null) {
            handlers = handler.getTransformationHandlers();
        }
        // Ensure the domain object has not been modified
        domainObjectChangedTest(path, source, mapping, domainObject);
        // Stamp the UOW on the domain object to avoid creation of separate UOWs during foreign-key validations
        if (domainObject.getUOW() == null)
            domainObject.setUOW(uow);
        // Reflect ProcessEventGraphs from newGraph to source - This will handle Pending/Warning Events during a clone/mass update
        if (newGraph != null && newGraph.getProcessEventGraphs() != null)
            source.setProcessEventGraphs(newGraph.getProcessEventGraphs());
        // Fire 'startBean' handler
        if (mode != DataTransformer.Mode.VALIDATE_ONLY && handlers != null) {
            for (ITransformationHandler transformationHandler : handlers) {
                transformationHandler.startBean(path, source, domainObject);
            }
        }
        // Reflect all normal fields
        for (Iterator it = mapping.getFields().iterator(); it.hasNext(); ) {
            String field = (String) it.next();
            // ignore read-only fields
            if (mapping.isReadOnly(field))
                continue;
            // values from the newGraph take precedence in CLONE/MASS_UPDATE mode
            if (mode == DataTransformer.Mode.CLONE) {
                // ignore dirty-read fields, and no-cloning fields unless a value is passed in the newGraph
                if (field.equals(mapping.getDirtyReadDataFieldName()) || (mapping.isNoCloning(field) && (newGraph == null || !newGraph.hasChanged(field))))
                    continue;
                Object value = getProperty(mapping.getDataFieldDescriptor(field), newGraph != null && newGraph.hasChanged(field) ? newGraph : source);
                updateProperty(mapping.getDomainFieldDescriptor(field), value, domainObject);
            } else if (mode == DataTransformer.Mode.MASS_UPDATE) {
                if (newGraph != null && newGraph.hasChanged(field)) {
                    Object value = getProperty(mapping.getDataFieldDescriptor(field), newGraph);
                    updateProperty(mapping.getDomainFieldDescriptor(field), value, domainObject);
                }
            } else {
                Object value = getProperty(mapping.getDataFieldDescriptor(field), source);
                if ((!domainObject.isDatabaseOccurence() && value != null) || source.hasChanged(field))
                    updateProperty(mapping.getDomainFieldDescriptor(field), value, domainObject);
            }
        }
        // Update flex fields
        if (source instanceof IFlexFields && domainObject instanceof IFlexFields) {
            if (log.isDebugEnabled())
                log.debug("Updating flex fields for " + path);
            FlexBean sFlexBean = ((IFlexFields) source).getFlexBean();
            FlexBean tFlexBean = ((IFlexFields) domainObject).getFlexBean();
            if (sFlexBean != null && tFlexBean != null) {
                for (DynaProperty flexProperty : tFlexBean.getDynaClass().getDynaProperties()) {
                    String name = flexProperty.getName();
                    // values from the newGraph take precedence in CLONE/MASS_UPDATE mode
                    if (mode == DataTransformer.Mode.CLONE) {
                        FlexBean nFlexBean = newGraph != null && newGraph instanceof IFlexFields ? ((IFlexFields) newGraph).getFlexBean() : null;
                        Object value = nFlexBean != null && nFlexBean.hasChanged(name) ? nFlexBean.get(name) : sFlexBean.get(name);
                        if (value != null)
                            tFlexBean.set(name, value);
                    } else if (mode == DataTransformer.Mode.MASS_UPDATE) {
                        FlexBean nFlexBean = newGraph != null && newGraph instanceof IFlexFields ? ((IFlexFields) newGraph).getFlexBean() : null;
                        if (nFlexBean != null && nFlexBean.hasChanged(name)) {
                            Object value = nFlexBean.get(name);
                            tFlexBean.set(name, value);
                        }
                    } else {
                        if (sFlexBean.hasChanged(name)) {
                            Object value = sFlexBean.get(name);
                            if (log.isDebugEnabled())
                                log.debug("Update flex field '" + name + '=' + value + "' on object '" + domainObject.getClass().getName() + '\'');
                            tFlexBean.set(name, value);
                        } else {
                            if (log.isDebugEnabled())
                                log.debug("Flex field '" + name + " has not changed on object " + source.getClass().getName());
                        }
                    }
                }
            }
        }
        // Reflect any foreign keys
        for (Iterator it = mapping.getForeignFields().iterator(); it.hasNext(); ) {
            String field = (String) it.next();
            // ignore read-only fields
            if (mapping.isReadOnly(field))
                continue;
            // It is possible that the foreign object may get resused, and only its fields may have been changed.
            // Hence also invoke the hasChanged() method on the foreign object itself
            Object value = null;
            boolean hasChanged = false;
            if (mode == DataTransformer.Mode.CLONE) {
                // ignore dirty-read fields, and no-cloning fields unless a value is passed in the newGraph
                if (field.equals(mapping.getDirtyReadDataFieldName()) || (mapping.isNoCloning(field) && (newGraph == null || !newGraph.hasChanged(field))))
                    continue;
                value = getProperty(mapping.getDataFieldDescriptor(field), newGraph != null && newGraph.hasChanged(field) ? newGraph : source);
                hasChanged = value != null;
            } else if (mode == DataTransformer.Mode.MASS_UPDATE) {
                if (newGraph != null && newGraph.hasChanged(field)) {
                    value = getProperty(mapping.getDataFieldDescriptor(field), newGraph);
                    hasChanged = true;
                }
            } else {
                value = getProperty(mapping.getDataFieldDescriptor(field), source);
                hasChanged = (!domainObject.isDatabaseOccurence() && value != null) || source.hasChanged(field);
            }
            if (!hasChanged && value != null && value instanceof GraphDataObject)
                hasChanged = ((GraphDataObject) value).hasChanged();
            if (hasChanged) {
                // need to map foreign keys back
                List targetKeys = mapping.getForeignKeys(field);
                GraphMapping fMapping = MappingFactory.getInstance(mapping.getDataFieldDescriptor(field).getPropertyType());
                Set sourceKeys = fMapping.getKeyFields();
                int i = 0;
                for (Iterator i2 = sourceKeys.iterator(); i2.hasNext(); i++) {
                    String sourceFld = (String) i2.next();
                    String targetFld = (String) targetKeys.get(i);
                    if (log.isDebugEnabled())
                        log.debug("Copy Foreign Key Field from " + sourceFld + " to " + targetFld);
                    if (value == null) {
                        // ForeignGraph is null. Null out the foreign-key
                        updateProperty(mapping.getRealDomainFieldDescriptor(targetFld), null, domainObject);
                    } else {
                        // Obtain the key-field from the ForeignGraph
                        Object value2 = getProperty(fMapping.getDataFieldDescriptor(sourceFld), value);
                        // The check is not required while cloning
                        if (mode == DataTransformer.Mode.CLONE || !(value instanceof GraphDataObject) || ((GraphDataObject) value).hasChanged(sourceFld))
                            updateProperty(mapping.getRealDomainFieldDescriptor(targetFld), value2, domainObject);
                    }
                }
                // Invoke the getter on the domain. An exception will be raised if the foreign-key is invalid
                if (log.isDebugEnabled())
                    log.debug("Performing validation on the domain object for the foreign object " + mapping.getDomainFieldName(field));
                PropertyDescriptor pd = mapping.getDomainFieldDescriptor(field);
                if (pd != null && pd.getReadMethod() != null) {
                    Method m = pd.getReadMethod();
                    if (!m.isAccessible())
                        m.setAccessible(true);
                    m.invoke(domainObject, (Object[]) null);
                }
            }
        }
        // Store Record
        if (mode == DataTransformer.Mode.VALIDATE_ONLY) {
            if (log.isDebugEnabled())
                log.debug("Domain object will not be persisted during prevalidation. Invoking the prevalidateBean handler");
            if (handlers != null) {
                for (ITransformationHandler transformationHandler : handlers) {
                    transformationHandler.prevalidateBean(path, source, domainObject);
                }
            }
        } else if (domainObject.isDatabaseOccurence()) {
            if (log.isDebugEnabled())
                log.debug("UOW.Update Domain Object");
            // Fire 'startBeanUpdate' handler
            if (handlers != null) {
                for (ITransformationHandler transformationHandler : handlers) {
                    transformationHandler.startBeanUpdate(path, source, domainObject);
                }
            }
            if (domainObject.isModified()) {
                uow.update(domainObject);
                if (handlers != null) {
                    for (ITransformationHandler transformationHandler : handlers) {
                        transformationHandler.setChangeDone(true);
                    }
                }
            }
            // Fire 'endBeanUpdate' handler
            if (handlers != null) {
                for (ITransformationHandler transformationHandler : handlers) {
                    transformationHandler.endBeanUpdate(path, source, domainObject);
                }
            }
        } else {
            if (handlers != null && mode == DataTransformer.Mode.CLONE) {
                if (log.isDebugEnabled()) {
                    log.debug("Invoke startBeanClone");
                }
                for (ITransformationHandler transformationHandler : handlers) {
                    transformationHandler.startBeanClone(path, source, domainObject, newGraph);
                }
            } else if (handlers != null && mode == DataTransformer.Mode.MASS_UPDATE) {
                if (log.isDebugEnabled()) {
                    log.debug("Invoke startBeanMassUpdate");
                }
                for (ITransformationHandler transformationHandler : handlers) {
                    transformationHandler.startBeanMassUpdate(path, source, domainObject, newGraph);
                }
            }
            if (log.isDebugEnabled())
                log.debug("UOW.Add Domain Object");
            // Fire 'startBeanAdd' handler
            if (handlers != null) {
                for (ITransformationHandler transformationHandler : handlers) {
                    transformationHandler.startBeanAdd(path, source, domainObject);
                }
            }
            uow.add(domainObject);
            if (handlers != null) {
                for (ITransformationHandler transformationHandler : handlers) {
                    transformationHandler.setChangeDone(true);
                }
            }
            // Fire 'endBeanAdd' handler
            if (handlers != null) {
                for (ITransformationHandler transformationHandler : handlers) {
                    transformationHandler.endBeanAdd(path, source, domainObject);
                }
            }
            if (handlers != null && mode == DataTransformer.Mode.CLONE) {
                if (log.isDebugEnabled()) {
                    log.debug("Invoke endBeanClone");
                }
                for (ITransformationHandler transformationHandler : handlers) {
                    transformationHandler.endBeanClone(path, source, domainObject, newGraph);
                }
            } else if (handlers != null && mode == DataTransformer.Mode.MASS_UPDATE) {
                if (log.isDebugEnabled()) {
                    log.debug("Invoke endBeanMassUpdate");
                }
                for (ITransformationHandler transformationHandler : handlers) {
                    transformationHandler.endBeanMassUpdate(path, source, domainObject, newGraph);
                }
            }
        }
        // Reflect any related objects
        for (Iterator it = mapping.getRelatedFields().iterator(); it.hasNext(); ) {
            String field = (String) it.next();
            if (mapping.isReadOnly(field))
                continue;
            Object value = null;
            if (mode == DataTransformer.Mode.CLONE) {
                // ignore no-cloning fields unless a value is passed in the newGraph
                if (mapping.isNoCloning(field) && (newGraph == null || !newGraph.hasChanged(field)))
                    continue;
                value = getProperty(mapping.getDataFieldDescriptor(field), newGraph != null && newGraph.hasChanged(field) ? newGraph : source);
            } else if (mode == DataTransformer.Mode.MASS_UPDATE) {
                if (newGraph != null && newGraph.hasChanged(field))
                    value = getProperty(mapping.getDataFieldDescriptor(field), newGraph);
            } else
                value = getProperty(mapping.getDataFieldDescriptor(field), source);
            if (value != null) {
                if (value.getClass().isArray()) {
                    // The related field is an array of objects (one-to-many)
                    Object[] values = (Object[]) value;
                    for (int i = 0; i < values.length; i++) {
                        // Assumes its a DAO....what else could it be?
                        GraphDataObject dao = (GraphDataObject) values[i];
                        if (dao != null) {
                            if (dao.getDeleteObject() != null && dao.getDeleteObject()) {
                                if (mode == DataTransformer.Mode.VALIDATE_ONLY) {
                                    if (log.isDebugEnabled())
                                        log.debug("The 'deleteObject' property is true. No prevalidations will be performed for the childBean.");
                                } else {
                                    if (log.isDebugEnabled())
                                        log.debug("The 'deleteObject' property is true. Invoking deleteChildBean()");
                                    deleteChildBean(path + '.' + field + '[' + i + ']', dao, uow, handler, domainObject, mapping, field);
                                }
                            } else {
                                Object newValue = newGraph != null ? getProperty(mapping.getDataFieldDescriptor(field), newGraph) : null;
                                GraphDataObject newDao = newValue != null && ((GraphDataObject[]) newValue).length > i ? ((GraphDataObject[]) newValue)[i] : null;
                                updateChildBean(path + '.' + field + '[' + i + ']', dao, uow, handler, domainObject, mapping, field, mode, newDao);
                            }
                        }
                    }
                } else {
                    // Or a single Object (one-to-one)
                    // Assumes its a DAO....what else could it be?
                    GraphDataObject dao = (GraphDataObject) value;
                    if (dao.getDeleteObject() != null && dao.getDeleteObject()) {
                        if (mode == DataTransformer.Mode.VALIDATE_ONLY) {
                            if (log.isDebugEnabled())
                                log.debug("The 'deleteObject' property is true. No prevalidations will be performed for the childBean.");
                        } else {
                            if (log.isDebugEnabled())
                                log.debug("The 'deleteObject' property is true. Invoking deleteChildBean()");
                            deleteChildBean(path + '.' + field, dao, uow, handler, domainObject, mapping, field);
                        }
                    } else {
                        GraphDataObject newDao = newGraph != null ? (GraphDataObject) getProperty(mapping.getDataFieldDescriptor(field), newGraph) : null;
                        updateChildBean(path + '.' + field, dao, uow, handler, domainObject, mapping, field, mode, newDao);
                    }
                }
            }
        }
        // Fire 'endBean' handler
        if (mode != DataTransformer.Mode.VALIDATE_ONLY && handlers != null) {
            for (ITransformationHandler transformationHandler : handlers) {
                transformationHandler.endBean(path, source, domainObject);
            }
        }
    } catch (SkipTransformException e) {
        if (log.isDebugEnabled()) {
            log.debug("Processing of " + path + " will be skipped", e);
        }
    } catch (ApplicationException e) {
        throw new ApplicationExceptions(e);
    }
}
Also used : Set(java.util.Set) ApplicationExceptions(org.jaffa.exceptions.ApplicationExceptions) PropertyDescriptor(java.beans.PropertyDescriptor) GraphDataObject(org.jaffa.soa.graph.GraphDataObject) Method(java.lang.reflect.Method) IFlexFields(org.jaffa.flexfields.IFlexFields) FlexBean(org.jaffa.flexfields.FlexBean) DynaProperty(org.apache.commons.beanutils.DynaProperty) ApplicationException(org.jaffa.exceptions.ApplicationException) Iterator(java.util.Iterator) GraphDataObject(org.jaffa.soa.graph.GraphDataObject) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

IFlexFields (org.jaffa.flexfields.IFlexFields)6 FlexBean (org.jaffa.flexfields.FlexBean)5 PropertyDescriptor (java.beans.PropertyDescriptor)3 InvocationTargetException (java.lang.reflect.InvocationTargetException)3 Method (java.lang.reflect.Method)3 ApplicationException (org.jaffa.exceptions.ApplicationException)3 ArrayList (java.util.ArrayList)2 Iterator (java.util.Iterator)2 List (java.util.List)2 Set (java.util.Set)2 DynaProperty (org.apache.commons.beanutils.DynaProperty)2 ApplicationExceptions (org.jaffa.exceptions.ApplicationExceptions)2 FrameworkException (org.jaffa.exceptions.FrameworkException)2 JaffaRulesFrameworkException (org.jaffa.rules.JaffaRulesFrameworkException)2 GraphDataObject (org.jaffa.soa.graph.GraphDataObject)2 BeanInfo (java.beans.BeanInfo)1 IntrospectionException (java.beans.IntrospectionException)1 AccessibleObject (java.lang.reflect.AccessibleObject)1 Properties (java.util.Properties)1 DynaBean (org.apache.commons.beanutils.DynaBean)1