view src/main/java/de/mpiwg/itgroup/ismi/entry/utils/PrivacityUtils.java @ 189:8aff920ec7c0

fix problem with making entities public when there are loops in the relations.
author Robert Casties <casties@mpiwg-berlin.mpg.de>
date Thu, 08 Nov 2018 20:15:02 +0100
parents 3d8b31508128
children c7fec83ab69a
line wrap: on
line source

package de.mpiwg.itgroup.ismi.entry.utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.mpi.openmind.cache.WrapperService;
import org.mpi.openmind.repository.bo.Entity;
import org.mpi.openmind.repository.bo.Relation;

public class PrivacityUtils {

    public static final Set<String> TEXTexcepts = new HashSet<String>(Arrays.asList("TEXT"));
    public static final Set<String> PERSONexcepts = new HashSet<String>(Arrays.asList("TEXT", "PERSON", "WITNESS",
            "CODEX", "TRANSFER_EVENT", "STUDY_EVENT", "COPY_EVENT", "MISATTRIBUTION", "MISIDENTIFICATION"));
    public static final Set<String> WITNESSexcepts = new HashSet<String>(Arrays.asList("WITNESS", "TEXT"));
    public static final Set<String> CODEXexcepts = new HashSet<String>(Arrays.asList("WITNESS"));
    public static final Set<String> COLLECTIONexcepts = new HashSet<String>(Arrays.asList("CODEX"));
    public static final Set<String> REPOSITORYexcepts = new HashSet<String>(Arrays.asList("COLLECTION", "STUDY_EVENT", "COPY_EVENT"));

    
	/**
	 * Change public state of the given entity.
	 * 
	 * Toggles public state if isPublic == null.
	 * 
	 * Returns the changed Entity (that needs to be saved).
	 * 
	 * @param entity
	 * @param isPublic
	 * @param wrapper
	 * @return
	 */
	public static Entity changeEntityPrivacity(Entity entity, Boolean isPublic, WrapperService wrapper) {
		// make sure attributes are loaded
		if (entity.isLightweight()) {
			entity = wrapper.getEntityContent(entity);
		}
		// toggle public if isPublic == null
		if (isPublic == null) {
			isPublic = !entity.getIsPublic();
		}
		// set public
		entity.setIsPublic(isPublic);
		return entity;
	}
	
	/**
	 * Change public state of all entities directly related to the given entity 
	 * (does not change the given entity).
	 * 
	 * Sets public state to given entity's state if isPublic == null.
	 * 
	 * Does not touch Entities of the types listed in exceptedTypes.
	 * 
	 * Returns a List of Entities that have been changed (and need to be saved).
	 * 
	 * @param entity
	 * @param isPublic
	 * @param wrapper
	 * @param exceptedTypes
	 * @param alreadyModified TODO
	 * @return
	 */
    public static Map<Long, Entity> setRelatedEntitiesPrivacity(Entity entity, Boolean isPublic, WrapperService wrapper,
            Set<String> exceptedTypes, Map<Long, Entity> alreadyModified) {
        Map<Long,Entity> modified = new HashMap<Long,Entity>();
        // make sure relations are loaded
        if (entity.isLightweight()) {
            entity = wrapper.getEntityContent(entity);
        }

        // use entity's public if isPublic == null
        if (isPublic == null) {
            isPublic = entity.getIsPublic();
        }

        // change source relations
        for (Relation rel : entity.getSourceRelations()) {
            if (!exceptedTypes.contains(rel.getTargetObjectClass())) {
                Long entId = rel.getTargetId();
                if (alreadyModified.containsKey(entId)) {
                	continue;
                }
                Entity ent = wrapper.getEntityById(entId);
                ent.setIsPublic(isPublic);
                modified.put(entId, ent);
            }
        }
        // change target relations
        for (Relation rel : entity.getTargetRelations()) {
            if (!exceptedTypes.contains(rel.getSourceObjectClass())) {
                Long entId = rel.getSourceId();
                if (alreadyModified.containsKey(entId)) {
                	continue;
                }
                Entity ent = wrapper.getEntityById(entId);
                ent.setIsPublic(isPublic);
                modified.put(entId, ent);
            }
        }
        return modified;
    }
	
	/**
	 * Change public state of a TEXT and all meaningfully related Entities.
	 * 
     * Sets public state to given entity's state if isPublic == null.
     * 
     * Returns a List of Entities that have been changed (and need to be saved).
     * 
	 * @param text
	 * @param isPublic
	 * @param wrapper
	 * @return
	 * @throws Exception 
	 */
    public static List<Entity> setTextAndMorePrivacity(Entity text, Boolean isPublic, List<String> report,
            WrapperService wrapper) throws Exception {
        Map<Long,Entity> modified = new HashMap<Long,Entity>();
        // make sure relations are loaded
        if (text.isLightweight()) {
            text = wrapper.getEntityContent(text);
        }

        // use entity's public if isPublic == null
        if (isPublic == null) {
            isPublic = text.getIsPublic();
        }

        /*
         * mark text public
         */
        text.setIsPublic(isPublic);
        modified.put(text.getId(), text);
        report.add("Set public="+isPublic+" on "+text.getShortString()+"\n");
        
        /*
         * mark directly related objects except TEXT
         */
        Map<Long, Entity> relatedEnts = setRelatedEntitiesPrivacity(text, isPublic, wrapper, TEXTexcepts, modified);
        modified.putAll(relatedEnts);
        report.add("Set public="+isPublic+" on related entities to "+text.getShortString()+" : ["+Entity.getShortStringList(relatedEnts.values())+"]\n");
       
        /*
         * follow relations of related objects
         */
        int cnt = 0;
        do {
        	Map<Long, Entity> nextRelEnts = new HashMap<Long,Entity>();
            for (Entity relEnt : relatedEnts.values()) {
                String entType = relEnt.getObjectClass();
                if (entType.equals("PERSON")) {
                    // PERSON
                    Map<Long, Entity> persRelEnts = setRelatedEntitiesPrivacity(relEnt, isPublic, wrapper, PERSONexcepts, modified);
                    modified.putAll(persRelEnts);
                    nextRelEnts.putAll(persRelEnts);
                    report.add("Set public="+isPublic+" on related entities to "+relEnt.getShortString()+" : ["+Entity.getShortStringList(persRelEnts.values())+"]\n");
                } else if (entType.equals("WITNESS")) {
                    // WITNESS
                	Map<Long, Entity> witRelEnts = setRelatedEntitiesPrivacity(relEnt, isPublic, wrapper, WITNESSexcepts, modified);
                    modified.putAll(witRelEnts);
                    nextRelEnts.putAll(witRelEnts);
                    report.add("Set public="+isPublic+" on related entities to "+relEnt.getShortString()+" : ["+Entity.getShortStringList(witRelEnts.values())+"]\n");
                } else if (entType.equals("CODEX")) {
                    // CODEX
                	Map<Long, Entity> codRelEnts = setRelatedEntitiesPrivacity(relEnt, isPublic, wrapper, CODEXexcepts, modified);
                    modified.putAll(codRelEnts);
                    nextRelEnts.putAll(codRelEnts);
                    report.add("Set public="+isPublic+" on related entities to "+relEnt.getShortString()+" : ["+Entity.getShortStringList(codRelEnts.values())+"]\n");
                } else if (entType.equals("COLLECTION")) {
                    // COLLECTION
                	Map<Long, Entity> colRelEnts = setRelatedEntitiesPrivacity(relEnt, isPublic, wrapper, COLLECTIONexcepts, modified);
                    modified.putAll(colRelEnts);
                    nextRelEnts.putAll(colRelEnts);
                    report.add("Set public="+isPublic+" on related entities to "+relEnt.getShortString()+" : ["+Entity.getShortStringList(colRelEnts.values())+"]\n");
                } else if (entType.equals("REPOSITORY")) {
                    // REPOSITORY
                	Map<Long, Entity> repRelEnts = setRelatedEntitiesPrivacity(relEnt, isPublic, wrapper, REPOSITORYexcepts, modified);
                    modified.putAll(repRelEnts);
                    nextRelEnts.putAll(repRelEnts);
                    report.add("Set public="+isPublic+" on related entities to "+relEnt.getShortString()+" : ["+Entity.getShortStringList(repRelEnts.values())+"]\n");
                } else if (entType.endsWith("_EVENT")) {
                    // *_EVENT: mark all related entities
                	Map<Long, Entity> evRelEnts = setRelatedEntitiesPrivacity(relEnt, isPublic, wrapper, null, modified);
                    modified.putAll(evRelEnts);
                    nextRelEnts.putAll(evRelEnts);
                    report.add("Set public="+isPublic+" on related entities to "+relEnt.getShortString()+" : ["+Entity.getShortStringList(evRelEnts.values())+"]\n");
                } else {
                    // everything else?
                }
            }
            if (nextRelEnts.equals(relatedEnts)) {
            	report.add("WARNING: had to break from loop!\n");
            	break;
            }
            // start with next level
            relatedEnts = nextRelEnts;
        } while (!relatedEnts.isEmpty() && ++cnt < 10);
        if (cnt == 10) {
        	report.add("ERROR: relation depth limit exceeded!");
            throw new Exception("Relation depth limit exceeded when marking text public!");
        }
        return new ArrayList<Entity>(modified.values());
	}
	
	
	
	public static List<Entity> changePrivacity4Person(Entity person, Boolean isPublic, WrapperService wrapper){
		List<Entity> saveList = new ArrayList<Entity>();
		
		if(person.isLightweight()){
			person = wrapper.getEntityContent(person);
		}
		
		boolean privacity = false;
		if(isPublic == null){
			privacity = !person.getIsPublic();
		}else{
			privacity = isPublic;
		}
		
		person.setIsPublic(privacity);
		saveList.add(person);
		
		List<Relation> relList = null;
		//loading relations
		if(privacity){
			relList = new ArrayList<Relation>(person.getSourceRelations());
			for (Relation rel : relList) {
				String relName = rel.getOwnValue();
				if (relName.equals("was_born_in") || 
						relName.equals("lived_in") || 
						relName.equals("was_student_of") || 
						relName.equals("has_role") || 
						relName.equals("died_in")) {
					Entity target = wrapper.getEntityById(rel.getTargetId());
					//target = wrapper.getEntityContent(target);
					target.setIsPublic(privacity);
					saveList.add(target);
				}
			}
		}
		
		relList = new ArrayList<Relation>(person.getTargetRelations());
		for (Relation rel : relList) {
			String relName = rel.getOwnValue();
			//title were be not included into this list
			if (relName.equals("is_alias_name_of") || relName.equals("is_prime_alias_name_of")) {
				Entity source = wrapper.getEntityById(rel.getSourceId());
				//source = wrapper.getEntityContent(source);
				source.setIsPublic(privacity);
				saveList.add(source);
			}
		}
		
		return saveList;
	}
	
	public static List<Entity> changePrivacity4Title(Entity title, Boolean isPublic, WrapperService wrapper){
		List<Entity> saveList = new ArrayList<Entity>();
	
		/*
		if(title.isLightweight()){
			title = wrapper.getEntityContent(title);
		}*/
		
		boolean privacity = false;
		if(isPublic == null){
			privacity = !title.getIsPublic();
		}else{
			privacity = isPublic;
		}
		
		title.setIsPublic(privacity);
		saveList.add(title);
		
		if(privacity){
			for(Entity ent : wrapper.getTargetsForSourceRelation(title, "has_subject", "SUBJECT", 1)){
				//if(ent.isLightweight())
				//	ent = wrapper.getEntityContent(ent);
				ent.setIsPublic(privacity);
				saveList.add(ent);
			} 
			
			for(Entity ent : wrapper.getTargetsForSourceRelation(title, "was_created_in", "PLACE", 1)){
				//if(ent.isLightweight())
				//	ent = wrapper.getEntityContent(ent);
				ent.setIsPublic(privacity);
				saveList.add(ent);
			}	
		}

		for(Entity ent : wrapper.getSourcesForTargetRelation(title, "is_alias_title_of", "ALIAS", -1)){
			//if(ent.isLightweight())
			//	ent = wrapper.getEntityContent(ent);
			ent.setIsPublic(privacity);
			saveList.add(ent);
		}
		
		return saveList;
	}
	
	
	/**
	 * 437080
	 * al-Taḏkiraẗ fī ʿilm al-hayʾaẗ 
	 * BIT(1)
	 * create:
	 * ALTER TABLE `openmind`.`node` ADD COLUMN `public` BIT(1) AFTER `possible_value`;
	 * modify:
	 * ALTER TABLE `openmind`.`node` MODIFY COLUMN `public` BIT(1) NOT NULL DEFAULT false;
	 * @param witness
	 * @param isPublic
	 * @param wrapper
	 * @return
	 */
	public static List<Entity> changePrivacity4Witness(Entity witness, Boolean isPublic, WrapperService wrapper){
		List<Entity> saveList = new ArrayList<Entity>();
		/*
		if(witness.isLightweight()){
			witness = wrapper.getEntityContent(witness);
		}
		*/
		boolean privacity = false;
		if(isPublic == null){
			privacity = !witness.getIsPublic();
		}else{
			privacity = isPublic;
		}
		
		witness.setIsPublic(privacity);
		saveList.add(witness);
		
		//changing references
		List<Entity> refEntities = wrapper.getSourcesForTargetRelation(witness.getId(), "is_reference_of", "REFERENCE", -1);
		for(Entity ref : refEntities){
			if(ref.isLightweight()){
				ref = wrapper.getEntityContent(ref);
			}
			ref.setIsPublic(privacity);
			saveList.add(ref);
		}
		
		//only if the witness is done public, the related entities will be changed.
		if(privacity){
			List<Entity> list = 
				wrapper.getTargetsForSourceRelation(witness.getId(),"is_part_of", "CODEX", 1);
			if (list.size() > 0) {
				Entity codex = list.get(0);
				codex.setIsPublic(privacity);
				saveList.add(codex);
				
				list = wrapper.getTargetsForSourceRelation(codex.getId(), "is_part_of", "COLLECTION", 1);
				if (list.size() > 0) {
					Entity collection = list.get(0);
					collection.setIsPublic(privacity);
					saveList.add(collection);
					
					list = wrapper.getTargetsForSourceRelation(collection.getId(), "is_part_of", "REPOSITORY", 1);
					if (list.size() > 0) {
						Entity repository = list.get(0);
						repository.setIsPublic(privacity);
						saveList.add(repository);
						
						list = wrapper.getTargetsForSourceRelation(repository.getId(), "is_in", "PLACE", 1);
						if(list.size() > 0){
							Entity city = list.get(0);
							city.setIsPublic(privacity);
							saveList.add(city);
							
							list = wrapper.getTargetsForSourceRelation(city.getId(), "is_part_of", "PLACE", 1);
							if(list.size() > 0){
								Entity country = list.get(0);
								country.setIsPublic(privacity);
								saveList.add(country);
							}
						}
					}
				}
			}
		}
		
		return saveList;
	}
	
}