argos/dmp-backend/core/src/main/java/eu/eudat/service/visibility/VisibilityServiceImpl.java

380 lines
17 KiB
Java

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(){
if (this.rulesBySources == null) return;
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);
}
@Override
public Map<FieldKey, Boolean> getVisibilityStates() {
this.calculateVisibility();
return visibility;
}
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;
}
}