2024-03-20 17:40:34 +01:00
package eu.eudat.service.visibility ;
import eu.eudat.commons.types.description.PropertyDefinitionEntity ;
import eu.eudat.commons.types.descriptiontemplate.* ;
import eu.eudat.model.persist.descriptionproperties.PropertyDefinitionPersist ;
import javax.ws.rs.NotSupportedException ;
import java.util.* ;
public class VisibilityServiceImpl implements VisibilityService {
private final DefinitionEntity definition ;
private final PropertyDefinition propertyDefinition ;
private Map < String , List < RuleWithTarget > > rulesBySources ;
private Map < FieldKey , Boolean > visibility ;
public VisibilityServiceImpl ( DefinitionEntity definition , PropertyDefinitionPersist propertyDefinition ) {
this . definition = definition ;
this . propertyDefinition = new PropertyDefinition ( propertyDefinition ) ;
}
public VisibilityServiceImpl ( DefinitionEntity definition , PropertyDefinitionEntity propertyDefinition ) {
this . definition = definition ;
this . propertyDefinition = new PropertyDefinition ( propertyDefinition ) ;
}
private void initRules ( ) {
2024-03-22 12:49:26 +01:00
if ( this . rulesBySources ! = null ) return ;
2024-03-20 17:40:34 +01:00
rulesBySources = new HashMap < > ( ) ;
for ( FieldEntity fieldEntity : this . definition . getAllField ( ) ) {
if ( fieldEntity . getVisibilityRules ( ) ! = null & & ! fieldEntity . getVisibilityRules ( ) . isEmpty ( ) ) {
for ( RuleEntity rule : fieldEntity . getVisibilityRules ( ) ) {
if ( ! rulesBySources . containsKey ( fieldEntity . getId ( ) ) ) rulesBySources . put ( fieldEntity . getId ( ) , new ArrayList < > ( ) ) ;
RuleWithTarget ruleWithTarget = new RuleWithTarget ( fieldEntity . getId ( ) , rule , fieldEntity ) ;
rulesBySources . get ( fieldEntity . getId ( ) ) . add ( ruleWithTarget ) ;
}
}
}
}
@Override
public boolean isVisible ( String id , Integer ordinal ) {
this . calculateVisibility ( ) ;
FieldKey fieldKey = new FieldKey ( id , ordinal ) ;
return this . visibility . getOrDefault ( fieldKey , false ) ;
}
2024-03-21 09:16:55 +01:00
@Override
public Map < FieldKey , Boolean > getVisibilityStates ( ) {
this . calculateVisibility ( ) ;
return visibility ;
}
2024-03-20 17:40:34 +01:00
private void calculateVisibility ( ) {
if ( visibility ! = null ) return ;
this . initRules ( ) ;
this . buildTargetVisibility ( ) ;
this . expandVisibilityToChildren ( ) ;
this . setDefaultVisibilityForNotCaclucted ( ) ;
this . hideParentIfAllChildrenAreHidden ( ) ;
}
private void buildTargetVisibility ( ) {
visibility = new HashMap < > ( ) ;
for ( Map . Entry < String , List < RuleWithTarget > > ruleForSource : rulesBySources . entrySet ( ) ) {
for ( RuleWithTarget rule : ruleForSource . getValue ( ) ) {
if ( propertyDefinition . getFieldSets ( ) ! = null & & ! propertyDefinition . getFieldSets ( ) . isEmpty ( ) ) {
for ( PropertyDefinitionFieldSet propertyDefinitionFieldSet : propertyDefinition . getFieldSets ( ) . values ( ) ) {
if ( propertyDefinitionFieldSet . getItems ( ) ! = null & & ! propertyDefinitionFieldSet . getItems ( ) . isEmpty ( ) ) {
for ( PropertyDefinitionFieldSetItem definitionFieldSetItem : propertyDefinitionFieldSet . getItems ( ) ) {
if ( definitionFieldSetItem . getFields ( ) ! = null & & ! definitionFieldSetItem . getFields ( ) . isEmpty ( ) ) {
for ( String key : definitionFieldSetItem . getFields ( ) . keySet ( ) ) {
if ( rule . getSource ( ) . equals ( key ) ) {
Field field = definitionFieldSetItem . getFields ( ) . get ( key ) ;
if ( definitionFieldSetItem . getFields ( ) . containsKey ( rule . getTarget ( ) ) ) { //Rule applies only for current multiple item
FieldKey fieldKey = new FieldKey ( rule . getTarget ( ) , definitionFieldSetItem . getOrdinal ( ) ) ;
boolean currentState = this . visibility . getOrDefault ( fieldKey , false ) ;
this . visibility . put ( fieldKey , currentState | | ruleIsTrue ( rule , field ) ) ;
} else if ( ! this . definition . getFieldById ( rule . getTarget ( ) ) . isEmpty ( ) | | ! this . definition . getFieldSetById ( rule . getTarget ( ) ) . isEmpty ( ) ) { //Rule applies to different fieldset, so we apply for all multiple items
List < Integer > ordinals = this . getKeyOrdinals ( rule . getTarget ( ) ) ;
for ( Integer ordinal : ordinals ) {
FieldKey fieldKey = new FieldKey ( rule . getTarget ( ) , ordinal ) ;
boolean currentState = this . visibility . getOrDefault ( fieldKey , false ) ;
this . visibility . put ( fieldKey , currentState | | ruleIsTrue ( rule , field ) ) ;
}
} else {
FieldKey fieldKey = new FieldKey ( rule . getTarget ( ) , null ) ; //Ordinal is null if target not on field
boolean currentState = this . visibility . getOrDefault ( fieldKey , false ) ;
this . visibility . put ( fieldKey , currentState | | ruleIsTrue ( rule , field ) ) ;
}
}
}
}
}
}
}
}
}
}
}
private List < Integer > getKeyOrdinals ( String key ) {
if ( propertyDefinition . getFieldSets ( ) ! = null & & ! propertyDefinition . getFieldSets ( ) . isEmpty ( ) ) {
for ( Map . Entry < String , PropertyDefinitionFieldSet > propertyDefinitionFieldSet : propertyDefinition . getFieldSets ( ) . entrySet ( ) ) {
if ( propertyDefinitionFieldSet . getKey ( ) . equals ( key ) ) return propertyDefinitionFieldSet . getValue ( ) . getItems ( ) . stream ( ) . map ( PropertyDefinitionFieldSetItem : : getOrdinal ) . toList ( ) ;
if ( propertyDefinitionFieldSet . getValue ( ) ! = null & & propertyDefinitionFieldSet . getValue ( ) . getItems ( ) ! = null & & ! propertyDefinitionFieldSet . getValue ( ) . getItems ( ) . isEmpty ( ) ) {
for ( PropertyDefinitionFieldSetItem definitionFieldSetItem : propertyDefinitionFieldSet . getValue ( ) . getItems ( ) ) {
if ( definitionFieldSetItem . getFields ( ) ! = null & & ! definitionFieldSetItem . getFields ( ) . isEmpty ( ) ) {
for ( String fieldKey : definitionFieldSetItem . getFields ( ) . keySet ( ) ) {
if ( fieldKey . equals ( key ) ) return propertyDefinitionFieldSet . getValue ( ) . getItems ( ) . stream ( ) . map ( PropertyDefinitionFieldSetItem : : getOrdinal ) . toList ( ) ;
}
}
}
}
}
}
return new ArrayList < > ( ) ;
}
private void expandVisibilityToChildren ( ) {
if ( this . definition . getPages ( ) = = null ) return ;
for ( PageEntity pageEntity : this . definition . getPages ( ) ) {
FieldKey fieldKey = new FieldKey ( pageEntity . getId ( ) , null ) ;
Boolean currentValue = this . visibility . getOrDefault ( fieldKey , null ) ;
this . expandPageVisibility ( pageEntity , currentValue ) ;
}
}
private void expandPageVisibility ( PageEntity pageEntity , Boolean parentVisibility ) {
if ( pageEntity . getSections ( ) = = null ) return ;
for ( SectionEntity sectionEntity : pageEntity . getSections ( ) ) {
FieldKey fieldKey = new FieldKey ( sectionEntity . getId ( ) , null ) ;
Boolean currentValue = this . visibility . getOrDefault ( fieldKey , null ) ;
if ( currentValue ! = null ) {
if ( parentVisibility ! = null & & ! parentVisibility ) { //Parent is hidden so all childs should be hidden
this . visibility . put ( fieldKey , false ) ;
this . expandSectionVisibility ( sectionEntity , currentValue ) ;
} else {
this . expandSectionVisibility ( sectionEntity , currentValue ) ;
}
} else {
if ( parentVisibility ! = null ) this . visibility . put ( fieldKey , parentVisibility ) ;
this . expandSectionVisibility ( sectionEntity , parentVisibility ) ;
}
}
}
private void expandSectionVisibility ( SectionEntity sectionEntity , Boolean parentVisibility ) {
if ( sectionEntity . getSections ( ) ! = null ) {
for ( SectionEntity subSectionEntity : sectionEntity . getSections ( ) ) {
FieldKey fieldKey = new FieldKey ( subSectionEntity . getId ( ) , null ) ;
Boolean currentValue = this . visibility . getOrDefault ( fieldKey , null ) ;
if ( currentValue ! = null ) {
if ( parentVisibility ! = null & & ! parentVisibility ) { //Parent is hidden so all childs should be hidden
this . visibility . put ( fieldKey , false ) ;
this . expandSectionVisibility ( subSectionEntity , currentValue ) ;
} else {
this . expandSectionVisibility ( subSectionEntity , currentValue ) ;
}
} else {
if ( parentVisibility ! = null ) this . visibility . put ( fieldKey , parentVisibility ) ;
this . expandSectionVisibility ( subSectionEntity , parentVisibility ) ;
}
}
}
if ( sectionEntity . getFieldSets ( ) ! = null ) {
for ( FieldSetEntity fieldSetEntity : sectionEntity . getFieldSets ( ) ) {
if ( propertyDefinition . getFieldSets ( ) ! = null & & ! propertyDefinition . getFieldSets ( ) . isEmpty ( ) ) {
PropertyDefinitionFieldSet propertyDefinitionFieldSet = propertyDefinition . getFieldSets ( ) . getOrDefault ( fieldSetEntity . getId ( ) , null ) ;
if ( propertyDefinitionFieldSet ! = null & & propertyDefinitionFieldSet . getItems ( ) ! = null & & ! propertyDefinitionFieldSet . getItems ( ) . isEmpty ( ) ) {
for ( PropertyDefinitionFieldSetItem definitionFieldSetItem : propertyDefinitionFieldSet . getItems ( ) ) {
FieldKey fieldKey = new FieldKey ( fieldSetEntity . getId ( ) , definitionFieldSetItem . getOrdinal ( ) ) ;
Boolean currentValue = this . visibility . getOrDefault ( fieldKey , null ) ;
if ( currentValue ! = null ) {
if ( parentVisibility ! = null & & ! parentVisibility ) { //Parent is hidden so all childs should be hidden
this . visibility . put ( fieldKey , false ) ;
this . expandFieldSetVisibility ( fieldSetEntity , currentValue , definitionFieldSetItem . getOrdinal ( ) ) ;
} else {
this . expandFieldSetVisibility ( fieldSetEntity , currentValue , definitionFieldSetItem . getOrdinal ( ) ) ;
}
} else {
if ( parentVisibility ! = null ) this . visibility . put ( fieldKey , parentVisibility ) ;
this . expandFieldSetVisibility ( fieldSetEntity , parentVisibility , definitionFieldSetItem . getOrdinal ( ) ) ;
}
}
}
}
}
}
}
private void expandFieldSetVisibility ( FieldSetEntity fieldSetEntity , Boolean parentVisibility , Integer ordinal ) {
if ( fieldSetEntity . getFields ( ) ! = null ) {
for ( FieldEntity fieldEntity : fieldSetEntity . getFields ( ) ) {
FieldKey fieldKey = new FieldKey ( fieldEntity . getId ( ) , ordinal ) ;
Boolean currentValue = this . visibility . getOrDefault ( fieldKey , null ) ;
if ( currentValue ! = null ) {
if ( parentVisibility ! = null & & ! parentVisibility ) { //Parent is hidden so all childs should be hidden
this . visibility . put ( fieldKey , false ) ;
}
} else if ( parentVisibility ! = null ) {
this . visibility . put ( fieldKey , parentVisibility ) ;
}
}
}
}
private void setDefaultVisibilityForNotCaclucted ( ) {
if ( this . definition . getPages ( ) = = null ) return ;
for ( PageEntity pageEntity : this . definition . getPages ( ) ) {
FieldKey fieldKey = new FieldKey ( pageEntity . getId ( ) , null ) ;
Boolean currentValue = this . visibility . getOrDefault ( fieldKey , null ) ;
if ( currentValue = = null ) this . visibility . put ( fieldKey , true ) ;
this . setDefaultPageVisibility ( pageEntity ) ;
}
}
private void setDefaultPageVisibility ( PageEntity pageEntity ) {
if ( pageEntity . getSections ( ) = = null ) return ;
for ( SectionEntity sectionEntity : pageEntity . getSections ( ) ) {
FieldKey fieldKey = new FieldKey ( sectionEntity . getId ( ) , null ) ;
Boolean currentValue = this . visibility . getOrDefault ( fieldKey , null ) ;
if ( currentValue = = null ) {
this . visibility . put ( fieldKey , true ) ;
this . setDefaultSectionVisibility ( sectionEntity ) ;
}
}
}
private void setDefaultSectionVisibility ( SectionEntity sectionEntity ) {
if ( sectionEntity . getSections ( ) ! = null ) {
for ( SectionEntity subSectionEntity : sectionEntity . getSections ( ) ) {
FieldKey fieldKey = new FieldKey ( subSectionEntity . getId ( ) , null ) ;
Boolean currentValue = this . visibility . getOrDefault ( fieldKey , null ) ;
if ( currentValue = = null ) {
this . visibility . put ( fieldKey , true ) ;
this . setDefaultSectionVisibility ( sectionEntity ) ;
}
}
}
if ( sectionEntity . getFieldSets ( ) ! = null ) {
for ( FieldSetEntity fieldSetEntity : sectionEntity . getFieldSets ( ) ) {
if ( propertyDefinition . getFieldSets ( ) ! = null & & ! propertyDefinition . getFieldSets ( ) . isEmpty ( ) ) {
PropertyDefinitionFieldSet propertyDefinitionFieldSet = propertyDefinition . getFieldSets ( ) . getOrDefault ( fieldSetEntity . getId ( ) , null ) ;
if ( propertyDefinitionFieldSet ! = null & & propertyDefinitionFieldSet . getItems ( ) ! = null & & ! propertyDefinitionFieldSet . getItems ( ) . isEmpty ( ) ) {
for ( PropertyDefinitionFieldSetItem definitionFieldSetItem : propertyDefinitionFieldSet . getItems ( ) ) {
FieldKey fieldKey = new FieldKey ( fieldSetEntity . getId ( ) , definitionFieldSetItem . getOrdinal ( ) ) ;
Boolean currentValue = this . visibility . getOrDefault ( fieldKey , null ) ;
if ( currentValue = = null ) {
this . visibility . put ( fieldKey , true ) ;
this . setDefaultFieldSetVisibility ( fieldSetEntity , definitionFieldSetItem . getOrdinal ( ) ) ;
}
}
}
}
}
}
}
private void setDefaultFieldSetVisibility ( FieldSetEntity fieldSetEntity , Integer ordinal ) {
if ( fieldSetEntity . getFields ( ) ! = null ) {
for ( FieldEntity fieldEntity : fieldSetEntity . getFields ( ) ) {
FieldKey fieldKey = new FieldKey ( fieldEntity . getId ( ) , ordinal ) ;
Boolean currentValue = this . visibility . getOrDefault ( fieldKey , null ) ;
if ( currentValue = = null ) {
this . visibility . put ( fieldKey , true ) ;
}
}
}
}
private void hideParentIfAllChildrenAreHidden ( ) {
if ( this . definition . getPages ( ) = = null ) return ;
for ( PageEntity pageEntity : this . definition . getPages ( ) ) {
FieldKey fieldKey = new FieldKey ( pageEntity . getId ( ) , null ) ;
boolean isCurrentHidden = this . isHiddenPageVisibilityIfAllChildrenIsHidden ( pageEntity ) ;
if ( this . visibility . getOrDefault ( fieldKey , true ) & & isCurrentHidden ) {
this . visibility . put ( fieldKey , false ) ;
}
}
}
private boolean isHiddenPageVisibilityIfAllChildrenIsHidden ( PageEntity pageEntity ) {
boolean isHidden = true ;
if ( pageEntity . getSections ( ) = = null ) return isHidden ;
for ( SectionEntity sectionEntity : pageEntity . getSections ( ) ) {
FieldKey fieldKey = new FieldKey ( sectionEntity . getId ( ) , null ) ;
boolean isCurrentHidden = this . isHiddenSectionIfAllChildrenIsHidden ( sectionEntity ) ;
if ( this . visibility . getOrDefault ( fieldKey , true ) & & isCurrentHidden ) {
this . visibility . put ( fieldKey , false ) ;
}
isHidden = isHidden & & isCurrentHidden ;
}
return isHidden ;
}
private boolean isHiddenSectionIfAllChildrenIsHidden ( SectionEntity sectionEntity ) {
boolean isHidden = true ;
if ( sectionEntity . getSections ( ) ! = null ) {
for ( SectionEntity subSectionEntity : sectionEntity . getSections ( ) ) {
FieldKey fieldKey = new FieldKey ( subSectionEntity . getId ( ) , null ) ;
boolean isCurrentHidden = this . isHiddenSectionIfAllChildrenIsHidden ( subSectionEntity ) ;
if ( this . visibility . getOrDefault ( fieldKey , true ) & & isCurrentHidden ) {
this . visibility . put ( fieldKey , false ) ;
}
isHidden = isHidden & & isCurrentHidden ;
}
}
if ( sectionEntity . getFieldSets ( ) ! = null ) {
for ( FieldSetEntity fieldSetEntity : sectionEntity . getFieldSets ( ) ) {
if ( propertyDefinition . getFieldSets ( ) ! = null & & ! propertyDefinition . getFieldSets ( ) . isEmpty ( ) ) {
PropertyDefinitionFieldSet propertyDefinitionFieldSet = propertyDefinition . getFieldSets ( ) . getOrDefault ( fieldSetEntity . getId ( ) , null ) ;
if ( propertyDefinitionFieldSet ! = null & & propertyDefinitionFieldSet . getItems ( ) ! = null & & ! propertyDefinitionFieldSet . getItems ( ) . isEmpty ( ) ) {
for ( PropertyDefinitionFieldSetItem definitionFieldSetItem : propertyDefinitionFieldSet . getItems ( ) ) {
FieldKey fieldKey = new FieldKey ( fieldSetEntity . getId ( ) , definitionFieldSetItem . getOrdinal ( ) ) ;
boolean isCurrentHidden = this . isHiddenFieldSetIfAllChildrenIsHidden ( fieldSetEntity , definitionFieldSetItem . getOrdinal ( ) ) ;
if ( this . visibility . getOrDefault ( fieldKey , true ) & & isCurrentHidden ) {
this . visibility . put ( fieldKey , false ) ;
}
isHidden = isHidden & & isCurrentHidden ;
}
}
}
}
}
return isHidden ;
}
private boolean isHiddenFieldSetIfAllChildrenIsHidden ( FieldSetEntity fieldSetEntity , Integer ordinal ) {
boolean isHidden = true ;
if ( fieldSetEntity . getFields ( ) ! = null ) {
for ( FieldEntity fieldEntity : fieldSetEntity . getFields ( ) ) {
FieldKey fieldKey = new FieldKey ( fieldEntity . getId ( ) , ordinal ) ;
Boolean currentValue = this . visibility . getOrDefault ( fieldKey , true ) ;
isHidden = isHidden & & ! currentValue ;
}
return isHidden ;
}
return true ;
}
private boolean ruleIsTrue ( RuleWithTarget rule , Field field ) {
if ( field ! = null ) {
eu . eudat . commons . enums . FieldType fieldType = rule . getFieldEntity ( ) ! = null & & rule . getFieldEntity ( ) . getData ( ) ! = null ? rule . getFieldEntity ( ) . getData ( ) . getFieldType ( ) : eu . eudat . commons . enums . FieldType . FREE_TEXT ;
if ( eu . eudat . commons . enums . FieldType . isTextType ( fieldType ) & & field . getTextValue ( ) ! = null & & ! field . getTextValue ( ) . isBlank ( ) ) {
if ( eu . eudat . commons . enums . FieldType . UPLOAD . equals ( fieldType ) ) {
throw new NotSupportedException ( " Upload file rule not supported " ) ;
} else {
return field . getTextValue ( ) . equals ( rule . getTextValue ( ) ) ;
}
}
else if ( eu . eudat . commons . enums . FieldType . isTextListType ( fieldType ) & & field . getTextListValue ( ) ! = null & & ! field . getTextListValue ( ) . isEmpty ( ) ) {
return rule . getTextListValue ( ) ! = null & &
new HashSet < > ( field . getTextListValue ( ) ) . containsAll ( rule . getTextListValue ( ) ) & &
new HashSet < > ( rule . getTextListValue ( ) ) . containsAll ( field . getTextListValue ( ) ) ;
}
else if ( eu . eudat . commons . enums . FieldType . isReferenceType ( fieldType ) ) {
return rule . getTextListValue ( ) ! = null & &
new HashSet < > ( field . getTextListValue ( ) ) . containsAll ( rule . getTextListValue ( ) ) & &
new HashSet < > ( rule . getTextListValue ( ) ) . containsAll ( field . getTextListValue ( ) ) ;
}
else if ( eu . eudat . commons . enums . FieldType . isDateType ( fieldType ) & & field . getDateValue ( ) ! = null ) return field . getDateValue ( ) . equals ( rule . getDateValue ( ) ) ;
else if ( eu . eudat . commons . enums . FieldType . isExternalIdentifierType ( fieldType ) & & field . getExternalIdentifier ( ) ! = null ) {
throw new NotSupportedException ( " External identifier rule not supported " ) ;
}
}
return false ;
}
}