use of org.jaffa.flexfields.IFlexFields in project jaffa-framework by jaffa-projects.
the class BeanHelper method setField.
/**
* This method will introspect the bean & get the setter method for the input propertyName.
* It will then try & convert the propertyValue to the appropriate datatype.
* Finally it will invoke the setter.
* @return A true indicates, the property was succesfully set to the passed value. A false indicates the property doesn't exist or the propertyValue passed is not compatible with the setter.
* @param bean The bean class to be introspected.
* @param propertyName The Property being searched for.
* @param propertyValue The value to be set.
* @throws IntrospectionException if an exception occurs during introspection.
* @throws IllegalAccessException if the underlying method is inaccessible.
* @throws InvocationTargetException if the underlying method throws an exception.
*/
public static boolean setField(Object bean, String propertyName, Object propertyValue) throws IntrospectionException, IllegalAccessException, InvocationTargetException {
boolean result = false;
if (bean instanceof DynaBean) {
try {
PropertyUtils.setProperty(bean, propertyName, propertyValue);
result = true;
} catch (NoSuchMethodException ignore) {
// If the bean is a FlexBean instance, then the field could exist on the associated persistentObject
if (bean instanceof FlexBean && ((FlexBean) bean).getPersistentObject() != null) {
try {
PropertyUtils.setProperty(((FlexBean) bean).getPersistentObject(), propertyName, propertyValue);
result = true;
} catch (NoSuchMethodException ignore2) {
}
}
}
} else {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
if (beanInfo != null) {
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
if (pds != null) {
for (PropertyDescriptor pd : pds) {
if (StringHelper.equalsIgnoreCaseFirstChar(pd.getName(), propertyName)) {
Method m = pd.getWriteMethod();
Object convertedPropertyValue = null;
if (propertyValue != null) {
if (pd.getPropertyType().isEnum()) {
convertedPropertyValue = findEnum(pd.getPropertyType(), propertyValue.toString());
} else {
try {
convertedPropertyValue = DataTypeMapper.instance().map(propertyValue, pd.getPropertyType());
} catch (Exception e) {
// do nothing
break;
}
}
}
m.invoke(bean, new Object[] { convertedPropertyValue });
result = true;
break;
}
}
}
}
try {
// Finally, check the FlexBean
if (!result && bean instanceof IFlexFields && ((IFlexFields) bean).getFlexBean() != null && ((IFlexFields) bean).getFlexBean().getDynaClass().getDynaProperty(propertyName) != null) {
((IFlexFields) bean).getFlexBean().set(propertyName, propertyValue);
result = true;
}
} catch (Exception ignore) {
}
}
return result;
}
use of org.jaffa.flexfields.IFlexFields in project jaffa-framework by jaffa-projects.
the class DataTransformer method buildGraphFromDomain.
/**
* Mould data from domain object and its related objects into a new JavaBean based
* domain object graph, based on the defined mapping rules.
*
* @param source Source object to mould data from, typically extends Persistent
* @param target Target object to mould data to, typically extends GraphDataObject
* @param graph The mapping class with the rules of how to map this source object
* @param filter Filter object that it is used to control what fields are populated or the target objects
* @param objectPath The path of this object being processed. This identifies possible parent
* and/or indexed entries where this object is contained.
* @param includeKeys true if key fields should be included in results regardless of the filters
* @param originalCriteria the original graph criteria.
* @param handler Possible bean handler to be used when processing this source object graph
* @throws ApplicationExceptions Thrown if one or more application logic errors are generated during moulding
* @throws FrameworkException Thrown if any runtime moulding error has occured.
*/
public static void buildGraphFromDomain(Object source, Object target, GraphMapping graph, MappingFilter filter, String objectPath, boolean includeKeys, GraphCriteria originalCriteria, ITransformationHandler handler) throws ApplicationExceptions, FrameworkException {
if (graph == null)
graph = MappingFactory.getInstance(target);
boolean useQueryDomain = graph.getQueryDomainClass() != null && source.getClass().isAssignableFrom(graph.getQueryDomainClass());
// throw new InstantiationException("A GraphMapping must be supplied");
if (filter == null)
filter = MappingFilter.getInstance(graph);
try {
// get list of target fileds to populate
String[] tFields = graph.getDataFieldNames();
if (tFields != null && tFields.length != 0)
for (int i = 0; i < tFields.length; i++) {
// Try to map a source to a target
String tName = tFields[i];
String fullName = tName;
if (objectPath != null)
fullName = objectPath + "." + fullName;
if (filter == null || filter.isFieldIncluded(fullName) || (includeKeys && graph.isKeyField(tName))) {
String sName = graph.getDomainFieldName(tName);
AccessibleObject tAccessibleObject = graph.getDataMutator(tName);
PropertyDescriptor tDesc = graph.getDataFieldDescriptor(tName);
PropertyDescriptor sDesc = useQueryDomain ? graph.getQueryDomainFieldDescriptor(tName) : graph.getDomainFieldDescriptor(tName);
if (useQueryDomain && sDesc == null)
continue;
// GraphObject descriptor with a setter, and a DO descriptor with a getter
if (sDesc == null)
log.error("No Getter for " + tName + " in path " + fullName);
// incase getter is not public, make it available
Method sm = sDesc.getReadMethod();
if (!sm.isAccessible())
sm.setAccessible(true);
// Set the value if the source and target are the same datatype
Class tClass = tDesc.getPropertyType();
Class sClass = sDesc.getPropertyType();
if (tClass.isAssignableFrom(sClass)) {
// Get the value being copied
Object sValue = sm.invoke(source, (Object[]) null);
setValue(tAccessibleObject, target, sValue);
if (log.isDebugEnabled())
log.debug("Set " + tName + " = " + sValue);
// See if there is a datatype mapper for these classes
} else if (DataTypeMapper.instance().isMappable(sClass, tClass)) {
// Get the value being copied
Object sValue = sm.invoke(source, (Object[]) null);
if (sValue != null) {
sValue = DataTypeMapper.instance().map(sValue, tClass);
if (log.isDebugEnabled())
log.debug("Set " + tName + " = " + sValue);
}
setValue(tAccessibleObject, target, sValue);
// See if target is a GraphObject, this could be a foreign object or one-to-one relationship...
} else if (GraphDataObject.class.isAssignableFrom(tClass) && IPersistent.class.isAssignableFrom(sClass)) {
// Get the mapper for the related GraphObject, if it has keys, it must be a foriegn object
if (graph.isForeignField(tName)) {
// look at foreign key fields, and make sure they are not null
List foreignKeys = graph.getForeignKeys(tName);
List foreignKeyValues = new ArrayList();
boolean nullKey = false;
for (Iterator k = foreignKeys.iterator(); k.hasNext(); ) {
String doProp = (String) k.next();
Object value = null;
PropertyDescriptor doPd = graph.getRealDomainFieldDescriptor(doProp);
if (doPd != null && doPd.getReadMethod() != null) {
Method m = doPd.getReadMethod();
if (!m.isAccessible())
m.setAccessible(true);
value = m.invoke(source, new Object[] {});
if (value == null)
nullKey = true;
foreignKeyValues.add(value);
} else {
throw new TransformException(TransformException.INVALID_FK_MAPPING, objectPath, doProp, graph.getDomainClassShortName());
}
}
if (nullKey) {
if (log.isDebugEnabled())
log.debug("Did not create skeleton object '" + tClass.getName() + "': one or more foreign key values missing.");
} else {
// Create the foreign object
if (log.isDebugEnabled())
log.debug("Creating foreign object - " + tClass.getName());
Object newGDO = newGraphDataObject(tClass);
boolean createSkeleton = true;
// Only retrieve related domain object and introspect if need
if (filter.areSubFieldsIncluded(fullName)) {
// read object and introspect all
if (log.isDebugEnabled())
log.debug("Read foreign object '" + fullName + "' and mold");
try {
Object sValue = sm.invoke(source, (Object[]) null);
if (sValue != null) {
DataTransformer.buildGraphFromDomain(sValue, newGDO, null, filter, fullName, true, originalCriteria, handler);
createSkeleton = false;
}
} catch (InvocationTargetException e) {
// If the foreign object is not found, create the skeleton
if (e.getCause() != null && e.getCause() instanceof InvalidForeignKeyException) {
if (log.isDebugEnabled())
log.debug("All foreign keys present, but foreign object does not exist", e);
} else
throw e;
}
}
if (createSkeleton) {
// just set foreign keys from current object
if (log.isDebugEnabled())
log.debug("Set keys on skeleton foreign object only");
GraphMapping graph2 = MappingFactory.getInstance(newGDO);
Set keys = graph2.getKeyFields();
if (keys == null || keys.size() != foreignKeyValues.size()) {
throw new TransformException(TransformException.MISMATCH_FK_MAPPING, objectPath, target.getClass().getName(), newGDO.getClass().getName());
}
int k2 = 0;
// Look through all the foreign keys on the skeleton object
for (Iterator k = keys.iterator(); k.hasNext(); k2++) {
String keyField = (String) k.next();
Object keyValue = foreignKeyValues.get(k2);
AccessibleObject accessibleObject = graph2.getDataMutator(keyField);
if (accessibleObject != null) {
setValue(accessibleObject, newGDO, keyValue);
} else {
throw new TransformException(TransformException.CANT_SET_KEY_FIELD, objectPath, keyField, newGDO.getClass().getName());
}
}
}
setValue(tAccessibleObject, target, newGDO);
if (log.isDebugEnabled())
log.debug("Set " + tName + " = " + newGDO);
}
} else {
// This is not a foreign object, must be a related object
if (filter.areSubFieldsIncluded(fullName)) {
// Create the related object
if (log.isDebugEnabled())
log.debug("Creating One-To-One object - " + tClass.getName());
Object newGDO = newGraphDataObject(tClass);
// read object and introspect all
if (log.isDebugEnabled())
log.debug("Read related object '" + fullName + "' and mold");
Object sValue = sm.invoke(source, (Object[]) null);
if (sValue != null) {
DataTransformer.buildGraphFromDomain(sValue, newGDO, null, filter, fullName, false, originalCriteria, handler);
setValue(tAccessibleObject, target, newGDO);
if (log.isDebugEnabled())
log.debug("Set " + tName + " = " + newGDO);
} else {
if (log.isDebugEnabled())
log.debug("Related object '" + fullName + "' not found. Ignore it!");
}
} else {
if (log.isDebugEnabled())
log.debug("No subfields for object " + fullName + " included. Object not retrieved");
}
}
// END-related object
// See if Target may be an array of GraphObject's
} else if (tClass.isArray() && GraphDataObject.class.isAssignableFrom(tClass.getComponentType()) && filter.areSubFieldsIncluded(fullName)) {
if (log.isDebugEnabled())
log.debug("Target is an array of GraphObject's");
if (sClass.isArray() && IPersistent.class.isAssignableFrom(sClass.getComponentType())) {
if (log.isDebugEnabled()) {
log.debug("Source is an array of Persistent Objects");
log.debug("Read related objects '" + fullName + "' and mold");
}
Object[] sArray = findRelatedObjects(source, sClass, sm, handler, originalCriteria, fullName);
if (sArray != null && sArray.length > 0) {
Object[] tArray = (Object[]) Array.newInstance(tClass.getComponentType(), sArray.length);
if (log.isDebugEnabled())
log.debug("Translate Array of Size " + sArray.length);
for (int j = 0; j < sArray.length; j++) {
Object newGDO = newGraphDataObject(tClass.getComponentType());
DataTransformer.buildGraphFromDomain(sArray[j], newGDO, null, filter, fullName, false, originalCriteria, handler);
tArray[j] = newGDO;
if (log.isDebugEnabled())
log.debug("Add to array [" + j + "] : " + newGDO);
}
setValue(tAccessibleObject, target, tArray);
if (log.isDebugEnabled())
log.debug("Set Array " + tName);
} else {
if (log.isDebugEnabled())
log.debug("Source Array is empty! Do Nothing");
}
}
// source is DO array
// Error... No way to map property
} else {
String err = "Can't Mold Property " + fullName + " from " + sClass.getName() + " to " + tClass.getName();
log.error(err);
throw new RuntimeException(err);
}
}
// is included in filtered fields
}
// By default all the domain-mapped flex fields will be loaded; unless excluded by a rule
if (source instanceof IFlexFields && target instanceof IFlexFields) {
String fullName = (objectPath != null ? objectPath + '.' : "") + "flexBean";
if (filter == null || filter.isFieldIncluded(fullName)) {
if (log.isDebugEnabled())
log.debug("Loading FlexBean " + fullName);
FlexBean sFlexBean = ((IFlexFields) source).getFlexBean();
FlexBean tFlexBean = ((IFlexFields) target).getFlexBean();
if (sFlexBean != null && tFlexBean != null) {
for (DynaProperty flexProperty : sFlexBean.getDynaClass().getDynaProperties()) {
String name = flexProperty.getName();
Boolean include = filter.includeField(fullName + '.' + name);
if (include != null ? include : ((FlexProperty) flexProperty).getFlexInfo().getProperty("domain-mapping") != null) {
Object value = sFlexBean.get(name);
if (value != null) {
if (log.isDebugEnabled())
log.debug("Loaded flex field '" + name + '=' + value + '\'');
tFlexBean.set(name, value);
}
}
}
}
}
}
// Clear changed fields on updated GraphObject
if (target != null && target instanceof GraphDataObject)
((GraphDataObject) target).clearChanges();
// Invoke the handler
if (handler != null) {
if (log.isDebugEnabled()) {
log.debug("Invoking the endBeanLoad on the handler");
}
for (ITransformationHandler transformationHandler : handler.getTransformationHandlers()) {
transformationHandler.endBeanLoad(objectPath, source, target, filter, originalCriteria);
}
}
} catch (ApplicationException e) {
throw new ApplicationExceptions(e);
} catch (IllegalAccessException e) {
TransformException me = new TransformException(TransformException.ACCESS_ERROR, objectPath, e.getMessage());
log.error(me.getLocalizedMessage(), e);
throw me;
} catch (InvocationTargetException e) {
ApplicationExceptions appExps = ExceptionHelper.extractApplicationExceptions(e);
if (appExps != null)
throw appExps;
FrameworkException fe = ExceptionHelper.extractFrameworkException(e);
if (fe != null)
throw fe;
TransformException me = new TransformException(TransformException.INVOCATION_ERROR, objectPath, e);
log.error(me.getLocalizedMessage(), me.getCause());
throw me;
} catch (InstantiationException e) {
TransformException me = new TransformException(TransformException.INSTANTICATION_ERROR, objectPath, e.getMessage());
log.error(me.getLocalizedMessage(), e);
throw me;
}
}
use of org.jaffa.flexfields.IFlexFields in project jaffa-framework by jaffa-projects.
the class RuleActor method getPropertyLabel.
/**
* A convenience method to return the property label to be used in error messages.
* It'll check for the label in the following order
* - Lookup a 'label' rule for this property
* - Return the property name
*
* @param targetObject The target Object.
* @param targetPropertyName The property for which the label is to be found.
* @return label for the property.
*/
protected String getPropertyLabel(Object targetObject, String targetPropertyName) {
String label = null;
String targetClassName = getActualClassName(targetObject.getClass());
try {
if (targetObject instanceof FlexBean) {
if (((FlexBean) targetObject).getDynaClass().getDynaProperty(targetPropertyName) == null && ((FlexBean) targetObject).getPersistentObject() != null) {
targetObject = ((FlexBean) targetObject).getPersistentObject();
targetClassName = targetObject.getClass().getName();
}
} else if (targetObject instanceof IFlexFields) {
if (((IFlexFields) targetObject).getFlexBean() != null && ((IFlexFields) targetObject).getFlexBean().getDynaClass().getDynaProperty(targetPropertyName) != null) {
targetObject = ((IFlexFields) targetObject).getFlexBean();
targetClassName = ((FlexBean) targetObject).getDynaClass().getName();
}
}
// Search for the first available property-level label rule
Map<String, List<RuleMetaData>> pkMap = getPropertyRuleMap(targetClassName, targetObject, "label");
if (pkMap != null && pkMap.containsKey(targetPropertyName)) {
List<RuleMetaData> rules = pkMap.get(targetPropertyName);
if (rules != null && rules.size() > 0) {
RuleMetaData rule = rules.get(0);
label = rule.getParameter(RuleMetaData.PARAMETER_VALUE);
}
}
} catch (Exception e) {
// do nothing
}
if (label == null) {
label = targetPropertyName;
}
return label;
}
use of org.jaffa.flexfields.IFlexFields in project jaffa-framework by jaffa-projects.
the class CandidateKeyValidator method invoke.
/**
* Apply the candidate-key validation.
*/
private void invoke(String targetClassName, IPersistent targetObject, UOW uow, RuleMetaData rule, AtomicCriteria criteriaToDiscardCurrentObject, Map<String, Object> keyValueMap) throws ApplicationException, ApplicationExceptions, FrameworkException {
if (log.isDebugEnabled()) {
log.debug("Applying " + rule + " on " + targetObject);
}
Criteria criteria = null;
String ck = rule.getParameter(RuleMetaData.PARAMETER_VALUE);
String[] ckFields = ck.split(",");
Boolean ignoreNull = Parser.parseBoolean(rule.getParameter("ignore-null"));
// Flex fields having null values are deleted from the database table.
// The persistence engine does not support queries of the type 'where not exists...'.
// Hence we'll retrieve all rows and throw an exception only if the fields in the collection are null in any of the rows
Collection<String> nullFields = null;
FlexClass flexClass = targetObject instanceof IFlexFields && ((IFlexFields) targetObject).getFlexBean() != null ? (FlexClass) ((IFlexFields) targetObject).getFlexBean().getDynaClass() : null;
boolean keyModified = false;
for (String ckField : ckFields) {
// determine if this is a flex field
FlexProperty flexProperty = flexClass != null ? flexClass.getDynaProperty(ckField) : null;
// Obtain the value
Object ckValue;
try {
ckValue = BeanHelper.getField(flexProperty != null ? ((IFlexFields) targetObject).getFlexBean() : targetObject, ckField);
if (ignoreNull != null && ignoreNull && ckValue == null) {
if (log.isDebugEnabled())
log.debug("Rule will be ignored since " + ckField + " is null");
return;
}
} catch (Exception e) {
if (log.isDebugEnabled())
log.debug("Exception thrown while trying to get value for the property " + ckField + ". It may not exist in the targetObject", e);
return;
}
// Perform the check only if the field is modified, or is NULL and Object has not been saved yet
if (!keyModified)
keyModified = isModified(flexProperty != null ? ((IFlexFields) targetObject).getFlexBean() : targetObject, ckField) || (ckValue == null && !targetObject.isDatabaseOccurence());
// and any other rule may cause the actual update to be executed.
if (flexProperty != null && flexProperty.getFlexInfo() != null && flexProperty.getFlexInfo().getProperty("domain-mapping") != null) {
ckField = flexProperty.getFlexInfo().getProperty("domain-mapping");
flexProperty = null;
}
// Add to criteria
if (criteria == null)
criteria = new Criteria();
if (ckValue == null) {
if (flexProperty != null) {
if (nullFields == null)
nullFields = new LinkedList<String>();
nullFields.add(ckField);
} else {
criteria.addCriteria(StringHelper.getUpper1(ckField), Criteria.RELATIONAL_IS_NULL);
}
} else {
if (flexProperty != null) {
Criteria flexCriteria = new Criteria();
flexCriteria.setTable(FlexFieldMeta.getName());
int i = 0;
for (String key : keyValueMap.keySet()) flexCriteria.addInnerCriteria("Key" + ++i, StringHelper.getUpper1(key));
flexCriteria.addCriteria(FlexFieldMeta.OBJECT_NAME, flexClass.getLogicalName());
flexCriteria.addCriteria(FlexFieldMeta.FIELD_NAME, flexProperty.getLogicalName());
flexCriteria.addCriteria(FlexFieldMeta.VALUE, DataTypeMapper.instance().map(ckValue, String.class, flexProperty.getFlexInfo() != null ? flexProperty.getFlexInfo().getProperty("layout") : null));
criteria.addAggregate(flexCriteria);
} else {
criteria.addCriteria(StringHelper.getUpper1(ckField), ckValue);
}
}
}
if (keyModified && criteria != null) {
if (criteriaToDiscardCurrentObject != null)
criteria.addAtomic(criteriaToDiscardCurrentObject);
criteria.setTable(targetClassName);
// try {
for (Object o : uow.query(criteria)) {
boolean violation = nullFields == null;
if (!violation) {
// Not a violation if any of the fields is not null
for (String ckField : nullFields) {
try {
violation = BeanHelper.getField(targetObject, ckField) == null;
if (!violation) {
break;
}
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Error in invoke method during query execution.", e);
}
throw new JaffaRulesFrameworkException("Error in invoke method during query execution on object: " + targetClassName, null, e);
}
}
}
if (violation) {
if (log.isDebugEnabled()) {
log.debug("Candidate key '" + ck + "' is not unique for the object " + targetObject);
}
String objectLabel = getObjectLabel(targetClassName, targetObject);
StringBuilder ckLabel = new StringBuilder();
for (int i = 0; i < ckFields.length; i++) {
if (i > 0) {
ckLabel.append(',');
}
ckLabel.append(getPropertyLabel(targetObject, ckFields[i]));
}
throw wrapException(new DuplicateCandidateKeyException(objectLabel, ckLabel.toString()), (T) targetObject, rule);
}
}
}
}
use of org.jaffa.flexfields.IFlexFields 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());
}
}
Aggregations