/
akolonin
/
aigents-java
Обзор
Документация
Войти
/
akolonin
/
aigents-java
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/main/java/net/webstructor/agent/Merger.java
184 строки
6 KB
Anton Kolonin
3.0.7 Graph-based search with structured-data-driven chat bot
06 сен 2020, 08:13
06 сен 2020, 08:13
f99395c
Код
Авторство
О чём код?
/* * MIT License * * Copyright (c) 2005-2018 by Anton Kolonin, Aigents * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package net.webstructor.agent; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import net.webstructor.al.AL; import net.webstructor.core.Storager; import net.webstructor.core.Thing; public class Merger { protected Storager storager; protected Body body; public Merger(Body body, Storager storager) { this.body = body; this.storager = storager; } //TODO: move the following to Merger class public void merge(Collection mergees) throws Exception { HashMap twinthings = new HashMap(); //for each thing for (Iterator it = mergees.iterator(); it.hasNext();) { Thing thing = (Thing)it.next(); //find twins //TODO: figure out the merge keys dynamically!? Collection twins = storager.get(thing,Schema.keys); if (AL.empty(twins)) { //must have at least itself //throw new Mistake("no thing for "+Writer.toString(thing)); continue;//TODO: what if no keys for merging? } else if (twins.size() == 1) { //itself continue; } else { ; } //TODO:ensure only couple twins can appear and not multiple //if (twins.size() > 2) //multiplicates can not have place normally //throw new Exception("multiple things for "+Writer.toString(thing)); //among the twins, find the one which is native Thing lucky = null; for (Iterator twit = twins.iterator(); twit.hasNext();) { Thing twin = (Thing)twit.next(); if (!mergees.contains(twin)) { lucky = twin;//merge to the first native break; } } if (lucky == null) { //TODO: can't happen under normal conditions! lucky = (Thing)twins.iterator().next();//mere left to the first } for (Iterator twit = twins.iterator(); twit.hasNext();) { Thing twin = (Thing)twit.next(); if (twin != lucky) twinthings.put(twin, lucky); } } //translate all what can be translated if (twinthings.size() > 0) replace(twinthings); //finally check for self-split Thing self = null; HashSet selves = new HashSet(); //for multiple classes of 'self' Collection classes = storager.getNamed(Schema.self); for (Iterator it = classes.iterator(); it.hasNext();) { //for all instances of the class Collection instances = storager.getByName(AL.is,it.next()); for (Iterator ii = instances.iterator(); ii.hasNext();) { Thing thing = (Thing)ii.next(); //consider native the first one if (self == null && !mergees.contains(thing)) self = thing; else selves.add(thing); } } twinthings.clear(); for (Iterator it = selves.iterator(); it.hasNext();) twinthings.put(it.next(), self); //translate the selves if (twinthings.size() > 0) replace(twinthings); } void replace(Map twinthings) { // re-link linkers of doomed twins with their successors // for all known properties String[] names = storager.getNames();//mapmap.getKeyStrings(); for (int i = 0; i < names.length; i++) { String name = names[i]; // for every Thing property if (storager.isThing(name)) { //get all objects referenced by that property Object[] things = storager.getObjects(name);//mapmap.getSubKeyObjects(name); if (!AL.empty(things)) for (int j = 0; j < things.length; j++) { // for any object referenced by this property Object o = things[j]; if (!(o instanceof Thing)) { body.error("Fatal error: mistype "+name+" "+o,null); continue; } Thing twin = (Thing)things[j]; Thing lucky = (Thing)twinthings.get(twin); if (lucky != null) { //if there is a translation needed HashSet victims = (HashSet)storager.get(name,twin);//mapmap.getObject(name, twin, false); if (!AL.empty(victims)) { victims = new HashSet( victims ); // copy to avoid concurrency for (Iterator it = victims.iterator(); it.hasNext();) { // for each such victim, translate twin to thing Thing victim = (Thing)it.next(); victim.delThing(name, twin); Thing translated = (Thing)twinthings.get(victim); if (translated != null) victim = translated; victim.addThing(name, lucky); } } } } } } /* int present = getThings().size(); int translations = twinthings.keySet().size(); */ // finally, just update twins and eliminate their replaced origins Collection things = twinthings.keySet(); for (Iterator it = things.iterator(); it.hasNext();) { Thing twin = (Thing)it.next(); Thing lucky = (Thing)twinthings.get(twin); if (lucky != null) { //TODO: why did we avoid cloning keys? //update thing from twin, except keys //lucky.update(twin,Array.sub(twin.getNamesAvailable(),Schema.keys));//before 20161002 lucky.update(twin,null);//after 20161002 //self-destroy boolean deleted = twin.del(); if (!deleted) body.debug("NOT DELETED: "+twin);//TODO:clear } } } }