use of org.jaffa.flexfields.FlexBean in project jaffa-framework by jaffa-projects.
the class AuditLogger method audit.
private void audit(IPersistent object, ChangeType changeType) throws ApplicationExceptions, FrameworkException {
IObjectRuleIntrospector introspector = RulesEngineFactory.getRulesEngine().getObjectRuleIntrospector(object);
Properties auditInfo = introspector.getAuditInfo();
if (auditInfo != null) {
// find auditInfo for the various properties
Map<String, Properties> auditInfoMap = introspector.getAuditInfoForProperties();
// obtain information for flex fields
FlexBean flexBean = null;
IObjectRuleIntrospector flexIntrospector = null;
Map<String, Properties> auditInfoOfFlexFields = null;
if (object instanceof IFlexFields) {
flexBean = ((IFlexFields) object).getFlexBean();
if (flexBean != null) {
flexIntrospector = RulesEngineFactory.getRulesEngine().getObjectRuleIntrospector(flexBean.getDynaClass().getName(), flexBean);
auditInfoOfFlexFields = flexIntrospector.getAuditInfoForProperties();
}
}
// determine if auditing is required
boolean doAudit = changeType == ChangeType.INSERT || changeType == ChangeType.DELETE;
if (changeType == ChangeType.UPDATE) {
// In update-mode, auditing is required only if one of the audit fields has changed
for (String propertyName : auditInfoMap.keySet()) {
if (object.isModified(propertyName) || object.isModified(StringHelper.getUpper1(propertyName))) {
doAudit = true;
break;
}
}
// check if flex fields have changed
if (!doAudit && auditInfoOfFlexFields != null) {
for (String propertyName : auditInfoOfFlexFields.keySet()) {
if (flexBean.hasChanged(propertyName)) {
doAudit = true;
break;
}
}
}
}
if (doAudit) {
// Raise PendingEventException if reason is required, but is missing in the MDC
Boolean reasonRequired = Parser.parseBoolean(auditInfo.getProperty("reason-required"));
if (reasonRequired != null && reasonRequired && MDC.get(AuditTransactionMeta.REASON) == null) {
if (log.isDebugEnabled())
log.debug("Throwing PendingEventException. 'Reason' needs to be provided in the MDC, since the reason-required attribute has been set to true in the audit rule for " + object.getClass());
throw new ApplicationExceptions(new PendingEventException("ReasonRequiredForAuditing"));
}
// Create AuditTransaction
createAuditTransaction();
// Create AuditTransactionObject
String objectId = createAuditTransactionObject(auditInfo.getProperty("name"), changeType);
// Create AuditTransactionField instances
createAuditTransactionFields(objectId, object, auditInfoMap, flexBean, auditInfoOfFlexFields);
} else {
if (log.isDebugEnabled())
log.debug("Audit logging not required since none of the auditable fields have changed in " + object);
}
} else {
if (log.isDebugEnabled())
log.debug("Audit logging not enabled for " + object.getClass());
}
}
use of org.jaffa.flexfields.FlexBean in project jaffa-framework by jaffa-projects.
the class FlexBeanConverter method convertOutbound.
/* (non-Javadoc)
* @see org.directwebremoting.Converter#convertOutbound(java.lang.Object, org.directwebremoting.OutboundContext)
*
* Copied from BasicObjectConverter
*
* Added custom code to convert the flexParams array as root level properties on the javascript object.
*/
@Override
public OutboundVariable convertOutbound(Object data, OutboundContext outctx) throws MarshallException {
FlexBean flexBean = (FlexBean) data;
// Where we collect out converted children
Map ovs = new TreeMap();
// We need to do this before collecing the children to save recurrsion
ObjectOutboundVariable ov = new ObjectOutboundVariable(outctx);
outctx.put(flexBean, ov);
try {
Map properties = getPropertyMapFromObject(flexBean, true, false);
for (Iterator it = properties.entrySet().iterator(); it.hasNext(); ) {
Map.Entry entry = (Map.Entry) it.next();
String name = (String) entry.getKey();
Property property = (Property) entry.getValue();
// CUSTOM CODE: Special handling for flexParams
if ("flexParams".equals(name)) {
FlexParam[] flexParams = flexBean.getFlexParams();
if (flexParams != null) {
for (FlexParam flexParam : flexParams) {
// Instead of the formatted value returned by flexParam.getValue(),
// use the original value returned by the flexBean. This will ensure
// standard DWR handling for those value.
Object value = flexBean.get(flexParam.getName());
if (value != null) {
// Added check to exclude null fields
OutboundVariable nested = getConverterManager().convertOutbound(value, outctx);
ovs.put(flexParam.getName(), nested);
}
}
}
} else {
Object value = property.getValue(flexBean);
if (value != null) {
// Added check to exclude null fields
OutboundVariable nested = getConverterManager().convertOutbound(value, outctx);
ovs.put(name, nested);
}
}
}
// Add the className to the object
if (flexBean != null) {
String className = flexBean.getClass().getSimpleName();
OutboundVariable var = getConverterManager().convertOutbound(className, outctx);
ovs.put("className", var);
}
} catch (MarshallException ex) {
throw ex;
} catch (Exception ex) {
throw new MarshallException(flexBean.getClass(), ex);
}
ov.init(ovs, getJavascript());
return ov;
}
use of org.jaffa.flexfields.FlexBean 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);
}
}
use of org.jaffa.flexfields.FlexBean in project jaffa-framework by jaffa-projects.
the class FieldInitializer method initialize.
/**
* Apply the initialize rule
*
* @param object the object to be initialized
* @param propertyName the name of the property to be initialized
* @param rule the rule used for initialization
* @throws Exception if any error occurs
*/
private void initialize(Object object, String propertyName, RuleMetaData rule) throws JaffaRulesFrameworkException {
// This is important, else the current value for the flex field will be unintentionally overwritten with the initial value.
if (object instanceof FlexBean) {
FlexBean flexBean = (FlexBean) object;
if (flexBean.getPersistentObject() != null && flexBean.getPersistentObject().isDatabaseOccurence()) {
if (logger.isDebugEnabled()) {
logger.debug("Rule " + rule + " on property" + propertyName + " of " + object + " cannot be applied since the targetObject is a FlexBean associated with an in-database persistentObject");
}
return;
}
}
if (logger.isDebugEnabled()) {
logger.debug("Applying " + rule + " on property" + propertyName + " of " + object);
}
String value = rule.getParameter(RuleMetaData.PARAMETER_VALUE);
String member = rule.getParameter(RuleMetaData.PARAMETER_MEMBER);
Boolean expression = Parser.parseBoolean(rule.getParameter(RuleMetaData.PARAMETER_EXPRESSION));
// evaluate expression if it exists
Object evaluatedValue = value;
if (expression != null && expression) {
String language = rule.getParameter(RuleMetaData.PARAMETER_LANGUAGE);
try {
evaluatedValue = ScriptHelper.instance(language).evaluate(null, value, object, rule.getSource(), rule.getLine() != null ? rule.getLine() : 0, 0);
} catch (Exception exception) {
throw new JaffaRulesFrameworkException("Error evaluating expression during initialize of object: " + object.getClass().getName(), null, exception);
}
if (evaluatedValue != null && !(evaluatedValue instanceof String)) {
evaluatedValue = DataTypeMapper.instance().map(evaluatedValue, String.class);
}
}
if (member == null) {
try {
BeanHelper.setField(object, propertyName, (String) evaluatedValue);
} catch (Exception exception) {
// The rules engine should be passive and ignore the exceptions that a setter might throw
if (logger.isDebugEnabled()) {
logger.debug("Set property '" + propertyName + " = " + evaluatedValue + "' has failed", exception);
}
}
} else {
try {
Field field = null;
Class clazz = object.getClass();
while (field == null) {
try {
field = clazz.getDeclaredField(member);
} catch (NoSuchFieldException e) {
if (clazz.getSuperclass() == null)
break;
clazz = clazz.getSuperclass();
}
}
if (field == null) {
if (logger.isDebugEnabled()) {
logger.debug("Member field " + member + " not found on class " + object.getClass().getName());
}
} else {
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(object, DataTypeMapper.instance().map(evaluatedValue, field.getType()));
}
} catch (Exception exception) {
// The rules engine should be passive and ignore the exceptions that a setter might throw
if (logger.isDebugEnabled()) {
logger.debug("Set member '" + member + " = " + evaluatedValue + "' has failed", exception);
}
}
}
}
Aggregations