private void addFromProperties( Iterable<XProperty> properties, String accessType, Set<String> persistentProperties, Audited allClassAudited) { for (XProperty property : properties) { // If this is not a persistent property, with the same access type as currently checked, // it's not audited as well. // If the property was already defined by the subclass, is ignored by superclasses if (persistentProperties.contains(property.getName()) && !auditedPropertiesHolder.contains(property.getName())) { final Value propertyValue = persistentPropertiesSource.getProperty(property.getName()).getValue(); if (propertyValue instanceof Component) { this.addFromComponentProperty( property, accessType, (Component) propertyValue, allClassAudited); } else { this.addFromNotComponentProperty(property, accessType, allClassAudited); } } else if (propertiesGroupMapping.containsKey(property.getName())) { // Retrieve embedded component name based on class field. final String embeddedName = propertiesGroupMapping.get(property.getName()); if (!auditedPropertiesHolder.contains(embeddedName)) { // Manage properties mapped within <properties> tag. final Value propertyValue = persistentPropertiesSource.getProperty(embeddedName).getValue(); this.addFromPropertiesGroup( embeddedName, property, accessType, (Component) propertyValue, allClassAudited); } } } }
/** * Checks if a property is audited and if yes, fills all of its data. * * @param property Property to check. * @param propertyData Property data, on which to set this property's modification store. * @param accessType Access type for the property. * @return False if this property is not audited. */ private boolean fillPropertyData( XProperty property, PropertyAuditingData propertyData, String accessType, Audited allClassAudited) { // check if a property is declared as not audited to exclude it // useful if a class is audited but some properties should be excluded final NotAudited unVer = property.getAnnotation(NotAudited.class); if ((unVer != null && !overriddenAuditedProperties.contains(property)) || overriddenNotAuditedProperties.contains(property)) { return false; } else { // if the optimistic locking field has to be unversioned and the current property // is the optimistic locking field, don't audit it if (globalCfg.isDoNotAuditOptimisticLockingField()) { final Version jpaVer = property.getAnnotation(Version.class); if (jpaVer != null) { return false; } } } if (!this.checkAudited(property, propertyData, allClassAudited)) { return false; } final String propertyName = propertyNamePrefix + property.getName(); propertyData.setName(propertyName); propertyData.setModifiedFlagName( MetadataTools.getModifiedFlagPropertyName(propertyName, globalCfg.getModifiedFlagSuffix())); propertyData.setBeanName(property.getName()); propertyData.setAccessType(accessType); addPropertyJoinTables(property, propertyData); addPropertyAuditingOverrides(property, propertyData); if (!processPropertyAuditingOverrides(property, propertyData)) { // not audited due to AuditOverride annotation return false; } addPropertyMapKey(property, propertyData); setPropertyAuditMappedBy(property, propertyData); setPropertyRelationMappedBy(property, propertyData); return true; }
private void addFromNotComponentProperty( XProperty property, String accessType, Audited allClassAudited) { final PropertyAuditingData propertyData = new PropertyAuditingData(); final boolean isAudited = fillPropertyData(property, propertyData, accessType, allClassAudited); if (isAudited) { // Now we know that the property is audited auditedPropertiesHolder.addPropertyAuditingData(property.getName(), propertyData); } }
private void addFromComponentProperty( XProperty property, String accessType, Component propertyValue, Audited allClassAudited) { final ComponentAuditingData componentData = new ComponentAuditingData(); final boolean isAudited = fillPropertyData(property, componentData, accessType, allClassAudited); if (propertyValue.isDynamic()) { if (isAudited) { throw new MappingException( "Audited dynamic-component properties are not supported. Consider applying @NotAudited annotation to " + propertyValue.getOwner().getEntityName() + "#" + property + "."); } return; } final PersistentPropertiesSource componentPropertiesSource = new ComponentPropertiesSource(reflectionManager, propertyValue); final ComponentAuditedPropertiesReader audPropReader = new ComponentAuditedPropertiesReader( ModificationStore.FULL, componentPropertiesSource, componentData, globalCfg, reflectionManager, propertyNamePrefix + MappingTools.createComponentPrefix(property.getName())); audPropReader.read(); if (isAudited) { // Now we know that the property is audited auditedPropertiesHolder.addPropertyAuditingData(property.getName(), componentData); } }
/** * Process the {@link AuditOverride} annotations for this property. * * @param property the property for which the {@link AuditOverride} annotations are being * processed * @param propertyData the Envers auditing data for this property * @return {@code false} if isAudited() of the override annotation was set to */ private boolean processPropertyAuditingOverrides( XProperty property, PropertyAuditingData propertyData) { // if this property is part of a component, process all override annotations if (this.auditedPropertiesHolder instanceof ComponentAuditingData) { final List<AuditOverride> overrides = ((ComponentAuditingData) this.auditedPropertiesHolder).getAuditingOverrides(); for (AuditOverride override : overrides) { if (property.getName().equals(override.name())) { // the override applies to this property if (!override.isAudited()) { return false; } else { if (override.auditJoinTable() != null) { propertyData.setJoinTable(override.auditJoinTable()); } } } } } return true; }
private void searchForRevisionInfoCfgInProperties( XClass clazz, ReflectionManager reflectionManager, MutableBoolean revisionNumberFound, MutableBoolean revisionTimestampFound, MutableBoolean modifiedEntityNamesFound, String accessType) { for (XProperty property : clazz.getDeclaredProperties(accessType)) { RevisionNumber revisionNumber = property.getAnnotation(RevisionNumber.class); RevisionTimestamp revisionTimestamp = property.getAnnotation(RevisionTimestamp.class); ModifiedEntityNames modifiedEntityNames = property.getAnnotation(ModifiedEntityNames.class); if (revisionNumber != null) { if (revisionNumberFound.isSet()) { throw new MappingException("Only one property may be annotated with @RevisionNumber!"); } XClass revisionNumberClass = property.getType(); if (reflectionManager.equals(revisionNumberClass, Integer.class) || reflectionManager.equals(revisionNumberClass, Integer.TYPE)) { revisionInfoIdData = new PropertyData(property.getName(), property.getName(), accessType, null); revisionNumberFound.set(); } else if (reflectionManager.equals(revisionNumberClass, Long.class) || reflectionManager.equals(revisionNumberClass, Long.TYPE)) { revisionInfoIdData = new PropertyData(property.getName(), property.getName(), accessType, null); revisionNumberFound.set(); // The default is integer revisionPropType = "long"; } else { throw new MappingException( "The field annotated with @RevisionNumber must be of type " + "int, Integer, long or Long"); } // Getting the @Column definition of the revision number property, to later use that info to // generate the same mapping for the relation from an audit table's revision number to the // revision entity revision number. Column revisionPropColumn = property.getAnnotation(Column.class); if (revisionPropColumn != null) { revisionPropSqlType = revisionPropColumn.columnDefinition(); } } if (revisionTimestamp != null) { if (revisionTimestampFound.isSet()) { throw new MappingException("Only one property may be annotated with @RevisionTimestamp!"); } XClass revisionTimestampClass = property.getType(); if (reflectionManager.equals(revisionTimestampClass, Long.class) || reflectionManager.equals(revisionTimestampClass, Long.TYPE) || reflectionManager.equals(revisionTimestampClass, Date.class) || reflectionManager.equals(revisionTimestampClass, java.sql.Date.class)) { revisionInfoTimestampData = new PropertyData(property.getName(), property.getName(), accessType, null); revisionTimestampFound.set(); } else { throw new MappingException( "The field annotated with @RevisionTimestamp must be of type " + "long, Long, java.util.Date or java.sql.Date"); } } if (modifiedEntityNames != null) { if (modifiedEntityNamesFound.isSet()) { throw new MappingException( "Only one property may be annotated with @ModifiedEntityNames!"); } XClass modifiedEntityNamesClass = property.getType(); if (reflectionManager.equals(modifiedEntityNamesClass, Set.class) && reflectionManager.equals(property.getElementClass(), String.class)) { modifiedEntityNamesData = new PropertyData(property.getName(), property.getName(), accessType, null); modifiedEntityNamesFound.set(); } else { throw new MappingException( "The field annotated with @ModifiedEntityNames must be of Set<String> type."); } } } }