/* * DrakkarKeel - An Enterprise Collaborative Search Platform * * The contents of this file are subject under the terms described in the * DRAKKARKEEL_LICENSE file included in this distribution; you may not use this * file except in compliance with the License. * * 2013-2014 DrakkarKeel Platform. */ package drakkar.stern.servant.service; import drakkar.oar.DocumentMetaData; import drakkar.oar.Documents; import drakkar.oar.QuerySource; import drakkar.oar.RecommendTracker; import drakkar.oar.Response; import drakkar.oar.ResultSetMetaData; import drakkar.oar.Seeker; import drakkar.oar.exception.RecommendationException; import drakkar.oar.exception.SeekerException; import drakkar.oar.exception.SessionException; import drakkar.oar.slice.client.ClientSidePrx; import static drakkar.oar.util.KeySearchable.*; import static drakkar.oar.util.KeyTransaction.*; import static drakkar.oar.util.NotifyAction.*; import drakkar.oar.util.OutputMonitor; import static drakkar.oar.util.SeekerAction.*; import drakkar.oar.util.Utilities; import drakkar.stern.callback.NotifyAMICallback; import drakkar.stern.controller.DataBaseController; import drakkar.stern.facade.event.FacadeListener; import drakkar.stern.tracker.cache.Count; import drakkar.stern.tracker.cache.SeekerInfo; import drakkar.stern.tracker.cache.SeekerRecommendResults; import drakkar.stern.tracker.cache.SeekerRecommendResults.IndexRecommendation; import drakkar.stern.tracker.cache.SeekerRecommendResults.RecommendResults; import drakkar.stern.tracker.cache.SeekerRecommendResults.SeekerRecData; import drakkar.stern.tracker.cache.SeekerRecommends; import drakkar.stern.tracker.cache.SeekerRecommends.RecomendsData; import drakkar.stern.tracker.cache.SeekerRecommends.SearcherResults; import drakkar.stern.tracker.cache.SeekerSearchResults; import drakkar.stern.tracker.cache.SeekerSearchResults.IndexMetaDoc; import drakkar.stern.tracker.cache.SeekerSearchResults.SearchData; import drakkar.stern.tracker.cache.SeekerSearchResults.SearchResults; import drakkar.stern.tracker.cache.SessionProfile; import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * The <code>ResponseUtilFactory</code> class is..... * Esta clase implementa los diferentes métodos de recomendación soportados por * el framework DrakkarKeel */ public class Recommender extends Service implements Recommendable { private long recommendationsCount = 0; /** * Constructor de la clase * * @param defaultSessionName * @param collaborativeSessions listado de sesiones * @param defaultSessionProfile */ public Recommender(String defaultSessionName, SessionProfile defaultSessionProfile, Map<String, SessionProfile> collaborativeSessions, Map<String, SessionProfile> htTempSessions) { super(defaultSessionName, defaultSessionProfile, collaborativeSessions, htTempSessions); } /** * Constructor de la clase * * @param defaultSessionName * @param defaultSessionProfile * @param collaborativeSessions listado de sesiones * @param dbController */ public Recommender(String defaultSessionName, SessionProfile defaultSessionProfile, Map<String, SessionProfile> collaborativeSessions, Map<String, SessionProfile> htTempSessions, DataBaseController dbController) { super(defaultSessionName, defaultSessionProfile, collaborativeSessions, htTempSessions, dbController); } /** * Constructor de la clase * * @param defaultSessionName * @param collaborativeSessions listado de sesiones * @param defaultSessionProfile * @param listener oyente de la aplicación servidora * @param dbController */ public Recommender(String defaultSessionName, SessionProfile defaultSessionProfile, Map<String, SessionProfile> collaborativeSessions, Map<String, SessionProfile> htTempSessions, FacadeListener listener, DataBaseController dbController) { super(defaultSessionName, defaultSessionProfile, collaborativeSessions, htTempSessions, listener, dbController); } /** * {@inheritDoc} */ public void recommendResults(String sessionName, Seeker emitter, String comments, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { int role = emitter.getRole(); if (role == Seeker.ROLE_POTENTIAL_MEMBER || sessionName.equalsIgnoreCase(defaultSessionName)) { throw new RecommendationException("The session or the seeker, don't support the invoked operation"); } else { SessionProfile sessionProfile = this.getSessionProfile(sessionName); Map<Seeker, ClientSidePrx> receptors = null; ResultSetMetaData list = null; List<Seeker> seekerList = null; switch (data.getSource()) { case LOCAL_SEARCH_RESULT: list = this.getSearchResults(sessionProfile, emitter, data); receptors = this.getReceptorsRecord(sessionProfile, emitter); this.notifyRecommendation(sessionName, emitter, receptors, comments, list); seekerList = new ArrayList<>(receptors.keySet()); this.registerRecommendations(sessionProfile, emitter, seekerList, list, comments); break; case RECOMMEND_SEARCH_RESULT: list = this.getRecommendResults(sessionProfile, emitter, data); receptors = this.getReceptorsRecord(sessionProfile, emitter); this.notifyRecommendation(sessionName, emitter, receptors, comments, list); seekerList = new ArrayList<>(receptors.keySet()); this.registerRecommendations(sessionProfile, emitter, seekerList, list, comments); break; default: throw new RecommendationException("El source es incorrecto"); } this.updateRecommendationsCount(sessionName, emitter); this.listener.notifyDoneRecommendation(); } } /** * {@inheritDoc} */ public void recommendResults(String sessionName, Seeker emitter, Seeker receptor, String comments, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { int role = emitter.getRole(); if (role == Seeker.ROLE_POTENTIAL_MEMBER || sessionName.equalsIgnoreCase(defaultSessionName)) { throw new RecommendationException("The session or the seeker, don't support the invoked operation"); } else { SessionProfile sessionProfile = this.getSessionProfile(sessionName); Map<Seeker, ClientSidePrx> receptors = null; ResultSetMetaData list = null; List<Seeker> seekers = new ArrayList<>(); seekers.add(receptor); switch (data.getSource()) { case LOCAL_SEARCH_RESULT: list = this.getSearchResults(sessionProfile, emitter, data); receptors = this.getReceptorsRecord(sessionProfile, seekers); this.notifyRecommendation(sessionName, emitter, receptors, comments, list); this.registerRecommendations(sessionProfile, emitter, seekers, list, comments); break; case RECOMMEND_SEARCH_RESULT: list = this.getRecommendResults(sessionProfile, emitter, data); receptors = this.getReceptorsRecord(sessionProfile, seekers); this.notifyRecommendation(sessionName, emitter, receptors, comments, list); this.registerRecommendations(sessionProfile, emitter, seekers, list, comments); break; default: throw new RecommendationException("El source es incorrecto"); } this.updateRecommendationsCount(sessionName, emitter); this.listener.notifyDoneRecommendation(); } } /** * {@inheritDoc} */ public void recommendResults(String sessionName, Seeker emitter, String comments, Documents docs, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { int role = emitter.getRole(); if (role == Seeker.ROLE_POTENTIAL_MEMBER || sessionName.equalsIgnoreCase(defaultSessionName)) { throw new RecommendationException("The session or the seeker, don't support the invoked operation"); } else { SessionProfile sessionProfile = this.getSessionProfile(sessionName); Map<Seeker, ClientSidePrx> receptors = this.getReceptorsRecord(sessionProfile, emitter); ResultSetMetaData list = null; List<Seeker> seekerList = null; switch (data.getSource()) { case LOCAL_SEARCH_RESULT: list = this.getSearchResults(sessionProfile, emitter, data, docs); this.notifyRecommendation(sessionName, emitter, receptors, comments, list); seekerList = new ArrayList<>(receptors.keySet()); this.registerRecommendations(sessionProfile, emitter, seekerList, list, comments); break; case RECOMMEND_SEARCH_RESULT: list = this.getRecommendResults(sessionProfile, emitter, data, docs); this.notifyRecommendation(sessionName, emitter, receptors, comments, list); seekerList = new ArrayList<>(receptors.keySet()); this.registerRecommendations(sessionProfile, emitter, seekerList, list, comments); break; case TRACK_SEARCH_RESULT: try { seekerList = new ArrayList<>(receptors.keySet()); this.collabSearchResults(sessionProfile, data, emitter, comments, docs, receptors); } catch (SQLException ex) { throw new RecommendationException(ex.getMessage()); } break; default: throw new RecommendationException("El source es incorrecto"); } this.updateRecommendationsCount(sessionName, emitter); this.listener.notifyDoneRecommendation(); } } /** * {@inheritDoc} */ public void recommendResults(String sessionName, Seeker emitter, Seeker receptor, Documents docs, String comments, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { int role = emitter.getRole(); if (role == Seeker.ROLE_POTENTIAL_MEMBER || sessionName.equalsIgnoreCase(defaultSessionName)) { throw new RecommendationException("The session or the seeker, don't support the invoked operation"); } else { SessionProfile sessionProfile = this.getSessionProfile(sessionName); ResultSetMetaData list = null; List<Seeker> seekers = new ArrayList<>(); seekers.add(receptor); Map<Seeker, ClientSidePrx> receptors = this.getReceptorsRecord(sessionProfile, seekers); switch (data.getSource()) { case LOCAL_SEARCH_RESULT: list = this.getSearchResults(sessionProfile, emitter, data, docs); this.notifyRecommendation(sessionName, emitter, receptors, comments, list); this.registerRecommendations(sessionProfile, emitter, seekers, list, comments); break; case RECOMMEND_SEARCH_RESULT: list = this.getRecommendResults(sessionProfile, emitter, data, docs); this.notifyRecommendation(sessionName, emitter, receptors, comments, list); this.registerRecommendations(sessionProfile, emitter, seekers, list, comments); break; case TRACK_SEARCH_RESULT: try { this.collabSearchResults(sessionProfile, data, emitter, comments, docs, receptors); } catch (SQLException ex) { throw new RecommendationException(ex.getMessage()); } break; default: throw new RecommendationException("El source es incorrecto"); } this.updateRecommendationsCount(sessionName, emitter); this.listener.notifyDoneRecommendation(); } } /** * {@inheritDoc} */ public void recommendResults(String sessionName, Seeker emitter, List<Seeker> receptors, String comments, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { int role = emitter.getRole(); if (role == Seeker.ROLE_POTENTIAL_MEMBER || sessionName.equalsIgnoreCase(defaultSessionName)) { throw new RecommendationException("The session or the seeker, don't support the invoked operation"); } else { SessionProfile sessionProfile = this.getSessionProfile(sessionName); Map<Seeker, ClientSidePrx> receptorsData = null; ResultSetMetaData list = null; List<Seeker> seekerList = null; switch (data.getSource()) { case LOCAL_SEARCH_RESULT: list = this.getSearchResults(sessionProfile, emitter, data); receptorsData = this.getReceptorsRecord(sessionProfile, receptors); this.notifyRecommendation(sessionName, emitter, receptorsData, comments, list); seekerList = new ArrayList<>(receptorsData.keySet()); this.registerRecommendations(sessionProfile, emitter, seekerList, list, comments); break; case RECOMMEND_SEARCH_RESULT: list = this.getRecommendResults(sessionProfile, emitter, data); receptorsData = this.getReceptorsRecord(sessionProfile, receptors); this.notifyRecommendation(sessionName, emitter, receptorsData, comments, list); seekerList = new ArrayList<>(receptorsData.keySet()); this.registerRecommendations(sessionProfile, emitter, seekerList, list, comments); break; default: throw new RecommendationException("El source es incorrecto"); } this.updateRecommendationsCount(sessionName, emitter); this.listener.notifyDoneRecommendation(); } } /** * {@inheritDoc} */ public void recommendResults(String sessionName, Seeker emitter, List<Seeker> receptors, Documents docs, String comments, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { int role = emitter.getRole(); if (role == Seeker.ROLE_POTENTIAL_MEMBER || sessionName.equalsIgnoreCase(defaultSessionName)) { throw new RecommendationException("The session or the seeker, don't support the invoked operation"); } else { SessionProfile sessionProfile = this.getSessionProfile(sessionName); Map<Seeker, ClientSidePrx> record = this.getReceptorsRecord(sessionProfile, receptors); ResultSetMetaData list = null; List<Seeker> seekerList = null; switch (data.getSource()) { case LOCAL_SEARCH_RESULT: list = this.getSearchResults(sessionProfile, emitter, data, docs); this.notifyRecommendation(sessionName, emitter, record, comments, list); seekerList = new ArrayList<>(record.keySet()); this.registerRecommendations(sessionProfile, emitter, seekerList, list, comments); break; case RECOMMEND_SEARCH_RESULT: list = this.getRecommendResults(sessionProfile, emitter, data, docs); this.notifyRecommendation(sessionName, emitter, record, comments, list); seekerList = new ArrayList<>(record.keySet()); this.registerRecommendations(sessionProfile, emitter, seekerList, list, comments); break; case TRACK_SEARCH_RESULT: try { this.collabSearchResults(sessionProfile, data, emitter, comments, docs, record); } catch (SQLException ex) { throw new RecommendationException(ex.getMessage()); } break; default: throw new RecommendationException("El source es incorrecto"); } this.updateRecommendationsCount(sessionName, emitter); this.listener.notifyDoneRecommendation(); } } /** * {@inheritDoc} */ public void recommendResults(String sessionName, Seeker emitter, String sessionNameRtr, Seeker receptor, String comments, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { int role = emitter.getRole(); if (role == Seeker.ROLE_POTENTIAL_MEMBER || sessionName.equalsIgnoreCase(defaultSessionName)) { throw new RecommendationException("The session or the seeker, don't support the invoked operation"); } else { SessionProfile sessionProfile = this.getSessionProfile(sessionName); SessionProfile sessionProfile2 = this.getSessionProfile(sessionNameRtr); Map<Seeker, ClientSidePrx> receptors = null; ResultSetMetaData list = null; List<Seeker> seekers = new ArrayList<>(); seekers.add(receptor); switch (data.getSource()) { case LOCAL_SEARCH_RESULT: list = this.getSearchResults(sessionProfile, emitter, data); receptors = this.getReceptorsRecord(sessionProfile2, seekers); this.notifyRecommendation(sessionNameRtr, emitter, receptors, comments, list); this.registerRecommendations(sessionProfile2, emitter, seekers, list, comments); break; case RECOMMEND_SEARCH_RESULT: list = this.getRecommendResults(sessionProfile, emitter, data); receptors = this.getReceptorsRecord(sessionProfile2, seekers); this.notifyRecommendation(sessionNameRtr, emitter, receptors, comments, list); this.registerRecommendations(sessionProfile2, emitter, seekers, list, comments); break; default: throw new RecommendationException("El source es incorrecto"); } this.updateRecommendationsCount(sessionName, emitter); this.listener.notifyDoneRecommendation(); } } /** * {@inheritDoc} */ public void recommendResults(String sessionName, Seeker emitter, String sessionNameRtrs, List<Seeker> receptors, String comments, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { int role = emitter.getRole(); if (role == Seeker.ROLE_POTENTIAL_MEMBER || sessionName.equalsIgnoreCase(defaultSessionName)) { throw new RecommendationException("The session or the seeker, don't support the invoked operation"); } else { SessionProfile sessionProfile = this.getSessionProfile(sessionName); SessionProfile sessionProfile2 = this.getSessionProfile(sessionNameRtrs); Map<Seeker, ClientSidePrx> receptorsData = null; ResultSetMetaData list = null; List<Seeker> seekerList = null; switch (data.getSource()) { case LOCAL_SEARCH_RESULT: list = this.getSearchResults(sessionProfile, emitter, data); receptorsData = this.getReceptorsRecord(sessionProfile2, receptors); this.notifyRecommendation(sessionNameRtrs, emitter, receptorsData, comments, list); seekerList = new ArrayList<>(receptorsData.keySet()); this.registerRecommendations(sessionProfile2, emitter, seekerList, list, comments); break; case RECOMMEND_SEARCH_RESULT: list = this.getRecommendResults(sessionProfile, emitter, data); receptorsData = this.getReceptorsRecord(sessionProfile2, receptors); this.notifyRecommendation(sessionNameRtrs, emitter, receptorsData, comments, list); seekerList = new ArrayList<>(receptorsData.keySet()); this.registerRecommendations(sessionProfile2, emitter, seekerList, list, comments); break; default: throw new RecommendationException("El source es incorrecto"); } this.updateRecommendationsCount(sessionName, emitter); this.listener.notifyDoneRecommendation(); } } /** * {@inheritDoc} */ public void recommendResults(String sessionName, Seeker emitter, String sessionNameRtr, Seeker receptor, Documents docs, String comments, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { int role = emitter.getRole(); if (role == Seeker.ROLE_POTENTIAL_MEMBER || sessionName.equalsIgnoreCase(defaultSessionName)) { throw new RecommendationException("The session or the seeker, don't support the invoked operation"); } else { SessionProfile sessionProfile = this.getSessionProfile(sessionName); SessionProfile sessionProfile2 = this.getSessionProfile(sessionNameRtr); List<Seeker> seekers = new ArrayList<>(); seekers.add(receptor); Map<Seeker, ClientSidePrx> receptors = this.getReceptorsRecord(sessionProfile2, seekers); ResultSetMetaData list = null; switch (data.getSource()) { case LOCAL_SEARCH_RESULT: list = this.getSearchResults(sessionProfile, emitter, data, docs); this.notifyRecommendation(sessionNameRtr, emitter, receptors, comments, list); this.registerRecommendations(sessionProfile2, emitter, seekers, list, comments); break; case RECOMMEND_SEARCH_RESULT: list = this.getRecommendResults(sessionProfile, emitter, data, docs); this.notifyRecommendation(sessionNameRtr, emitter, receptors, comments, list); this.registerRecommendations(sessionProfile2, emitter, seekers, list, comments); break; case TRACK_SEARCH_RESULT: try { this.collabSearchResults(sessionProfile, data, emitter, comments, docs, receptors); } catch (SQLException ex) { throw new RecommendationException(ex.getMessage()); } break; default: throw new RecommendationException("El source es incorrecto"); } this.updateRecommendationsCount(sessionName, emitter); this.listener.notifyDoneRecommendation(); } } /** * {@inheritDoc} */ public void recommendResults(String sessionName, Seeker emitter, String sessionNameRtrs, List<Seeker> receptors, Documents docs, String comments, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { int role = emitter.getRole(); if (role == Seeker.ROLE_POTENTIAL_MEMBER || sessionName.equalsIgnoreCase(defaultSessionName)) { throw new RecommendationException("The session or the seeker, don't support the invoked operation"); } else { SessionProfile sessionProfile = this.getSessionProfile(sessionName); SessionProfile sessionProfile2 = this.getSessionProfile(sessionNameRtrs); Map<Seeker, ClientSidePrx> record = this.getReceptorsRecord(sessionProfile2, receptors); ResultSetMetaData list = null; List<Seeker> seekerList = null; switch (data.getSource()) { case LOCAL_SEARCH_RESULT: list = this.getSearchResults(sessionProfile, emitter, data, docs); this.notifyRecommendation(sessionNameRtrs, emitter, record, comments, list); seekerList = new ArrayList<>(record.keySet()); this.registerRecommendations(sessionProfile2, emitter, seekerList, list, comments); break; case RECOMMEND_SEARCH_RESULT: list = this.getRecommendResults(sessionProfile, emitter, data, docs); this.notifyRecommendation(sessionNameRtrs, emitter, record, comments, list); seekerList = new ArrayList<>(record.keySet()); this.registerRecommendations(sessionProfile2, emitter, seekerList, list, comments); break; case TRACK_SEARCH_RESULT: try { this.collabSearchResults(sessionProfile, data, emitter, comments, docs, record); } catch (SQLException ex) { throw new RecommendationException(ex.getMessage()); } break; default: throw new RecommendationException("El source es incorrecto"); } this.updateRecommendationsCount(sessionName, emitter); this.listener.notifyDoneRecommendation(); } } /**********************************Utilities***********************/ /** * Este método devuelve todos los resultados de búsqueda a partir de una consulta determinada, * de todos los buscadores empleados ó selección de estos. * * @param sessionProfile nombre de la sesión * @param emitter miembro que realiza la recomendación * @return results listado con los resultados de la búsqueda * * @throws SessionException * @throws UserNotExistException * */ private ResultSetMetaData getDocuments(SessionProfile sessionProfile, Seeker emitter, QuerySource data) throws SessionException, SeekerException, RecommendationException { SeekerSearchResults searchValues = sessionProfile.getSeekerSearchResults(); boolean flag = !searchValues.record.isEmpty(); //si existen resultados de búsq. para la sesión especificada if (flag) { String query = data.getQuery(); flag = searchValues.record.containsKey(emitter); if (flag) { SearchData searchData = searchValues.record.get(emitter); SearchResults searchResults = searchData.values.get(query); if (searchResults == null) { throw new RecommendationException("The query " + query + " doesn´t exist"); } int[] searcher = data.getSearchers(); ResultSetMetaData temp = null; if (searcher == null) {//todos los resultados obtenidos por buscadores temp = new ResultSetMetaData(query, searchResults.getDocumentMap()); return temp; } else { Map<Integer, List<DocumentMetaData>> resultsHash = new HashMap<>(); List<DocumentMetaData> metaDocs = null; for (int item : searcher) { metaDocs = searchResults.results.get(item).getDocuments(); if (metaDocs != null) { resultsHash.put(item, metaDocs); } } temp = new ResultSetMetaData(data.getQuery(), resultsHash); return temp; } } else { throw new SeekerException("The seeker '" + emitter.getUser() + "' is not registered in the session '" + sessionProfile.getProperties().getSessionName() + "'."); } } else { throw new SessionException("The session '" + sessionProfile.getProperties().getSessionName() + "' doesn't exist."); } } /** * Este método devuelve una selección los resultados de búsqueda a partir de una consulta determinada, * para buscadores seleccionados * * @param sessionProfile nombre de la sesión * @param emitter miembro que realiza la recomendación * @return results listado con los resultados de la búsqueda * * @throws SessionException * @throws UserNotExistException * */ private ResultSetMetaData getDocuments(SessionProfile sessionProfile, Seeker emitter, Documents docs, QuerySource data) throws SessionException, SeekerException, RecommendationException { SeekerSearchResults searchValues = sessionProfile.getSeekerSearchResults(); boolean flag = !searchValues.record.isEmpty(); //si existen resultados de búsq. para la sesión especificada if (flag) { flag = searchValues.record.containsKey(emitter); if (flag) { String query = data.getQuery(); SearchData searchData = searchValues.record.get(emitter); SearchResults searchResults = searchData.values.get(query); if (searchResults == null) { throw new RecommendationException("The query " + query + " doesn´t exist"); } ResultSetMetaData temp = null; Map<Integer, List<DocumentMetaData>> resultsHash = new HashMap<>(); IndexMetaDoc indexMDoc; List<DocumentMetaData> metaDocs = null; // documentos a recomendar por bucadores Map<Integer, List<Integer>> values = docs.getDocs(); Set<Integer> searchersID = values.keySet(); List<Integer> docsIndex = null; for (Integer item : searchersID) { docsIndex = new ArrayList<>(values.get(item)); indexMDoc = searchResults.results.get(item); if (indexMDoc != null) { metaDocs = new ArrayList<>(); for (Integer i : docsIndex) { metaDocs.add(indexMDoc.index.get(i)); } resultsHash.put(item, metaDocs); } } temp = new ResultSetMetaData(data.getQuery(), resultsHash); return temp; } else { throw new SeekerException("The seeker '" + emitter.getUser() + "' is not registered in the session '" + sessionProfile.getProperties().getSessionName() + "'."); } } else { throw new SessionException("The session '" + sessionProfile.getProperties().getSessionName() + "' doesn't exist."); } } /** * Este método devuelve todos los resultados de recomendaciones recibidas a partir de una consulta determinada, * de todos los buscadores empleados ó selección de estos. * * @param sessionProfile nombre de la sesión * @param emitter miembro que realiza la recomendación * @return results listado con los resultados de la búsqueda * * @throws SessionException * @throws UserNotExistException * */ private ResultSetMetaData getRecommends(SessionProfile sessionProfile, Seeker emitter, QuerySource data) throws SessionException, SeekerException, RecommendationException { SeekerRecommendResults recommendValues = sessionProfile.getSeekerRecommendResults(); boolean flag = !recommendValues.record.isEmpty(); String sessionName = sessionProfile.getProperties().getSessionName(); //si existen resultados de búsq. para la sesión especificada if (flag) { flag = recommendValues.record.containsKey(emitter); if (flag) { String query = data.getQuery(); SeekerRecData results = recommendValues.record.get(emitter); RecommendResults recommendResults = results.values.get(data.getQuery()); if (recommendResults == null) { throw new RecommendationException("The query " + query + " doesn´t exist"); } int[] searcher = data.getSearchers(); ResultSetMetaData temp = null; if (searcher == null) {//todos los resultados obtenidos por buscadores temp = new ResultSetMetaData(query, recommendResults.getDocuments()); return temp; } else { Map<Integer, List<DocumentMetaData>> resultsHash = new HashMap<>(); List<DocumentMetaData> metaDocs = null; for (int i : searcher) { metaDocs = recommendResults.results.get(i).getDocuments(); if (metaDocs != null) { resultsHash.put(i, metaDocs); } } temp = new ResultSetMetaData(query, resultsHash); return temp; } } else { throw new SeekerException("The seeker '" + emitter.getUser() + "' is not registered in the session '" + sessionProfile.getProperties().getSessionName() + "'."); } } else { throw new SessionException("The session '" + sessionName + "' doesn't exist."); } } /** * Este método devuelve una selección los resultados de recomendaciones recibidas a partir de una consulta determinada, * para buscadores seleccionados * * @param sessionProfile nombre de la sesión * @param emitter miembro que realiza la recomendación * @return results listado con los resultados de la búsqueda * * @throws SessionException * @throws UserNotExistException * */ private ResultSetMetaData getRecommends(SessionProfile sessionProfile, Seeker emitter, Documents docs, QuerySource data) throws SessionException, SeekerException, RecommendationException { SeekerRecommendResults recommendValues = sessionProfile.getSeekerRecommendResults(); boolean flag = !recommendValues.record.isEmpty(); String sessionName = sessionProfile.getProperties().getSessionName(); //si existen resultados de búsq. para la sesión especificada if (flag) { flag = recommendValues.record.containsKey(emitter); if (flag) { String query = data.getQuery(); SeekerRecData results = recommendValues.record.get(emitter); RecommendResults recommendResults = results.values.get(data.getQuery()); if (recommendResults == null) { throw new RecommendationException("The query " + query + " doesn´t exist"); } ResultSetMetaData temp = null; Map<Integer, List<DocumentMetaData>> resultsHash = new HashMap<>(); SeekerRecommendResults.IndexRecommendation indexMDoc; List<DocumentMetaData> metaDocs = null; Map<Integer, List<Integer>> values = docs.getDocs(); List<Integer> docsIndex = null; Set<Integer> searchersID = values.keySet(); for (Integer item : searchersID) { docsIndex = new ArrayList<>(values.get(item)); indexMDoc = recommendResults.results.get(item); if (indexMDoc != null) { metaDocs = new ArrayList<>(); for (Integer i : docsIndex) { metaDocs.add(indexMDoc.index.get(i)); } resultsHash.put(item, metaDocs); } } temp = new ResultSetMetaData(query, resultsHash); return temp; } else { throw new SeekerException("The seeker '" + emitter.getUser() + "' is not registered in the session '" + sessionProfile.getProperties().getSessionName() + "'."); } } else { throw new SessionException("The session '" + sessionName + "' doesn't exist."); } } /** * Este método se emplea para actualizar la relación de recomendaciones efectuadas * por los miembros de un sesión y el total general de la misma. * * @param sessionProfile nombre de la sesión a la que pertenece el miembro. * @param seeker miembro que ejecuta la búsqueda. */ private void updateRecommendationsCount(String sessionName, Seeker seeker) { SessionProfile recordSession = this.collaborativeSessions.get(sessionName); int count = 0; //se obtiene la relación de recomendaciones efectuadas por los // miembros de la sesión. Count membRecCount = recordSession.getSeekersRecommendations(); boolean flag = !membRecCount.record.isEmpty(); if (flag) { try { // se obtiene e incrementa el número de recomendaciones del miembro count = membRecCount.record.get(seeker); count++; // si el miembro no se encuentra registrado, se procede // a realizar su registro al capturar la expeción. } catch (NullPointerException e) { membRecCount.record.put(seeker, 1); } } else { membRecCount.record.put(seeker, 1); } // se incrementa el valor de las recomendaciones efectuadas // durante la actual sesión del servidor. this.recommendationsCount++; // se incrementa el valor de las recomendaciones efectuadas // por la la sesión durante actual sesión del servidor. count = recordSession.getRecommendationsCount(); count++; } private Response buildResponse(Seeker emitter, ResultSetMetaData recommendation, String comments) { Map<Object, Object> hash = new HashMap<>(4); // se confecciona el objeto Response hash.put(OPERATION, NOTIFY_EXPLICIT_RECOMMENDATION); hash.put(SEEKER_EMITTER, emitter); hash.put(RECOMMENDATION, recommendation); hash.put(COMMENT, comments); Response response = new Response(hash); return response; } /** * {@inheritDoc} */ public long getRecommendationsCount() { return this.recommendationsCount; } /** * {@inheritDoc} */ public long getRecommendationsCount(String sessionName) throws SessionException { SessionProfile recordSession = getSessionProfile(sessionName); int count = recordSession.getRecommendationsCount(); return count; } /** * {@inheritDoc} */ public long getRecommendationsCount(String sessionName, Seeker seeker) throws SessionException, SeekerException { SessionProfile recordSession = getSessionProfile(sessionName); Count members = recordSession.getSeekersRecommendations(); boolean flag = members.record.containsKey(seeker); if (flag) { int count = members.record.get(seeker); return count; } else { throw new SeekerException("The seeker '" + seeker.getUser() + "' is not registered in the session '" + sessionName + "'."); } } private ResultSetMetaData getSearchResults(SessionProfile sessionProfile, Seeker emitter, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { SeekerInfo members = sessionProfile.getSeekerInfo(); boolean flag = members.record.containsKey(emitter); // se comprueba que el miembro que emite la recommendación sea miembro // de la sesión, en caso contrario se lanza una excepción del tipo // UserNotExistException. if (flag) { // se obtiene la relación de los resultados de búquedas anteriores de // los miembros de la sesión SeekerSearchResults searches = sessionProfile.getSeekerSearchResults(); flag = !searches.record.isEmpty(); // se comprueba que la sesión cuente con registros de resultados de // búsquedas anteriores y que el miembro que emite la recomendación, // se encuentre en estos, en caso contrario se lanza una excepción // del tipo RecommendationException. if (flag) { flag = searches.record.containsKey(emitter); if (flag) { ResultSetMetaData recommendation = getDocuments(sessionProfile, emitter, data); return recommendation; } else { throw new RecommendationException("The seeker '" + emitter.getUser() + "'doesn't have previous results of search"); } } else { throw new RecommendationException("The session '" + sessionProfile.getProperties().getSessionName() + "'doesn't have previous results of search"); } } else { throw new SeekerException("The seeker '" + emitter.getUser() + "' is not registered in the session '" + sessionProfile.getProperties().getSessionName() + "'."); } } private ResultSetMetaData getSearchResults(SessionProfile sessionProfile, Seeker emitter, QuerySource data, Documents docs) throws SessionException, SeekerException, RecommendationException, IOException { SeekerInfo members = sessionProfile.getSeekerInfo(); boolean flag = members.record.containsKey(emitter); // se comprueba que el miembro que emite la recommendación sea miembro // de la sesión, en caso contrario se lanza una excepción del tipo // UserNotExistException. if (flag) { // se obtiene la relación de los resultados de búquedas anteriores de // los miembros de la sesión SeekerSearchResults searches = sessionProfile.getSeekerSearchResults(); flag = !searches.record.isEmpty(); // se comprueba que la sesión cuente con registros de resultados de // búsquedas anteriores y que el miembro que emite la recomendación, // se encuentre en estos, en caso contrario se lanza una excepción // del tipo RecommendationException. if (flag) { flag = searches.record.containsKey(emitter); if (flag) { ResultSetMetaData recommendation = getDocuments(sessionProfile, emitter, docs, data); return recommendation; } else { throw new RecommendationException("The seeker '" + emitter.getUser() + "'doesn't have previous results of search"); } } else { throw new RecommendationException("The session '" + sessionProfile.getProperties().getSessionName() + "'doesn't have previous results of search"); } } else { throw new SeekerException("The seeker '" + emitter.getUser() + "' is not registered in the session '" + sessionProfile.getProperties().getSessionName() + "'."); } } private ResultSetMetaData getRecommendResults(SessionProfile sessionProfile, Seeker emitter, QuerySource data) throws SessionException, SeekerException, RecommendationException, IOException { SeekerInfo members = sessionProfile.getSeekerInfo(); if (members.record.containsKey(emitter)) { SeekerRecommendResults recommend = sessionProfile.getSeekerRecommendResults(); if (!recommend.record.isEmpty()) { if (recommend.record.containsKey(emitter)) { ResultSetMetaData recommendation = getDocuments(sessionProfile, emitter, data); return recommendation; } else { throw new RecommendationException("The seeker '" + emitter.getUser() + "'doesn't have previous results of search"); } } else { throw new RecommendationException("The session '" + sessionProfile.getProperties().getSessionName() + "'doesn't have previous results of search"); } } else { throw new SeekerException("The seeker '" + emitter.getUser() + "' is not registered in the session '" + sessionProfile.getProperties().getSessionName() + "'."); } } private ResultSetMetaData getRecommendResults(SessionProfile sessionProfile, Seeker emitter, QuerySource data, Documents docs) throws SessionException, SeekerException, RecommendationException, IOException { SeekerInfo members = sessionProfile.getSeekerInfo(); if (members.record.containsKey(emitter)) { SeekerSearchResults searches = sessionProfile.getSeekerSearchResults(); if (!searches.record.isEmpty()) { if (searches.record.containsKey(emitter)) { ResultSetMetaData recommendation = getDocuments(sessionProfile, emitter, docs, data); return recommendation; } else { throw new RecommendationException("The seeker '" + emitter.getUser() + "'doesn't have previous results of search"); } } else { throw new RecommendationException("The session '" + sessionProfile.getProperties().getSessionName() + "'doesn't have previous results of search"); } } else { throw new SeekerException("The seeker '" + emitter.getUser() + "' is not registered in the session '" + sessionProfile.getProperties().getSessionName() + "'."); } } private Map<Seeker, ClientSidePrx> getReceptorsRecord(SessionProfile sessionProfile, List<Seeker> seekers) { SeekerInfo seekersPrx = sessionProfile.getSeekerInfo(); Map<Seeker, ClientSidePrx> seekersData = new HashMap<>(); for (Seeker seeker : seekers) { seekersData.put(seeker, seekersPrx.record.get(seeker)); } return seekersData; } // Devuelve todos los usuarios de la sesión(exceptuando el emisor) con sus correspondientes obj proxies private Map<Seeker, ClientSidePrx> getReceptorsRecord(SessionProfile sessionProfile, Seeker emitter) { SeekerInfo seekersPrx = sessionProfile.getSeekerInfo(); Map<Seeker, ClientSidePrx> seekersData = new HashMap<>(); List<Seeker> seekers = new ArrayList<>(seekersPrx.record.keySet()); seekers.remove(emitter); for (Seeker seeker : seekers) { seekersData.put(seeker, seekersPrx.record.get(seeker)); } return seekersData; } private void notifyRecommendation(String sessionName, Seeker emitter, Map<Seeker, ClientSidePrx> receptors, String comments, ResultSetMetaData list) throws RecommendationException { Response rsp = this.buildResponse(emitter, list, comments); byte[] array = null; try { array = rsp.toArray(); // se serializa el objeto Response } catch (IOException ex) { throw new RecommendationException(ex.getMessage()); } Set<Seeker> sekkers = receptors.keySet(); ClientSidePrx clientSidePrx; for (Seeker seeker : sekkers) { clientSidePrx = receptors.get(seeker); clientSidePrx.notify_async(new NotifyAMICallback(seeker, "notifyRecommendation"), array); this.listener.notifyDoneRecommendation(); } this.updateRecommendationsCount(sessionName, emitter); } private void registerRecommendations(final SessionProfile session, final Seeker emitter, final List<Seeker> seekers, final ResultSetMetaData list, final String comments) { final DataBaseController control = this.dbController; Thread thread = new Thread(new Runnable() { @SuppressWarnings("unchecked") public void run() { try { String date = Utilities.getDate(); String query = list.getQuery(); updateRecordSession(query, list, seekers, session); List<String> seekersUsers = new ArrayList<>(); for (Seeker seeker : seekers) { seekersUsers.add(seeker.getUser()); } RecommendTracker data = null; List<DocumentMetaData> metaDocs = null; List<RecommendTracker> recommendData = new ArrayList<>(); Map<Integer, List<RecommendTracker>> hash = new HashMap<>(); Set<Integer> searchers = list.getResultsMap().keySet(); for (Integer searcher : searchers) { metaDocs = list.getResultList(searcher); recommendData.clear(); for (DocumentMetaData docs : metaDocs) { data = new RecommendTracker(seekersUsers, emitter.getUser(), date, comments, docs.getPath(), docs.getIndex(), query, searcher); recommendData.add(data); } hash.put(searcher, (ArrayList<RecommendTracker>) ((ArrayList) recommendData).clone()); } registerSeekerRecommendations(emitter, session.getSeekerRecommends(), hash, query); //BD control.saveRecomendation(session.getProperties().getSessionName(), emitter.getUser(), comments, list, seekers); } catch (SQLException ex) { OutputMonitor.printStream("SQL", ex); } } }); thread.start(); } /** * Este método es empleado para actualizar el registro de usuario una vez efectuada * una recomendación * * @param query término de la consulta * @param list resultados de la búsqueda * @param documentsCount cantidad de documentos encontrados * @param seeker receptores de la recomendación * @param recordSession registro de la sesión */ private void updateRecordSession(String query, ResultSetMetaData list, List<Seeker> seekers, SessionProfile recordSession) { SeekerRecommendResults recommendProfile = recordSession.getSeekerRecommendResults(); //si existen resultados de búsq. para la sesión especificada boolean flag = !recommendProfile.record.isEmpty(); if (flag) { for (Seeker seeker : seekers) { updateRecordSession(query, list, seeker, recommendProfile); } } else { // si no existen registros de recomendaciones para la sesión especificada se // procede a registrar la misma para almacenar los resultados del usuario SeekerRecData results = recommendProfile.new SeekerRecData(); RecommendResults recommendResults = recommendProfile.new RecommendResults(); Map<Integer, List<DocumentMetaData>> hash = list.getResultsMap(); Set<Integer> searchersEnum = hash.keySet(); for (Integer searcher : searchersEnum) { recommendResults.results.put(searcher, recommendProfile.new IndexRecommendation(hash.get(searcher))); } results.values.put(query, recommendResults); // se registra el miembro con los resultados obtenidos for (Seeker item : seekers) { recommendProfile.record.put(item, results); } } } /** * Almacenar en caché las recomendaciones hechas por un usuario * * @param emitter * @param seekerRecommends * @param recommends * @param query */ public void registerSeekerRecommendations(Seeker emitter, SeekerRecommends seekerRecommends, Map<Integer, List<RecommendTracker>> recommends, String query) { RecomendsData recomendsData; SearcherResults searcherResults = null; if (seekerRecommends.values.containsKey(emitter)) { recomendsData = seekerRecommends.values.get(emitter); if (recomendsData.data.containsKey(query)) { searcherResults = recomendsData.data.get(query); searcherResults.insertRecommendation(recommends); } else { searcherResults = seekerRecommends.new SearcherResults(recommends); recomendsData.data.put(query, searcherResults); } } else { //no ha hecho recomendaciones recomendsData = seekerRecommends.new RecomendsData(); searcherResults = seekerRecommends.new SearcherResults(recommends); recomendsData.data.put(query, searcherResults); seekerRecommends.values.put(emitter, recomendsData); } } /** * Este método es empleado para actualizar el registro de cada miembro de la sesión * colaborativa, una vez que se efectúa una recomendación * * @param query término de la consulta * @param list lista de resultados. * @param seeker miembro al cual actualizar su registro. * @param searchTemp registro de búsquedas de la sesión a la que pertenece el usuario. */ private void updateRecordSession(String query, ResultSetMetaData list, Seeker seeker, SeekerRecommendResults recommendProfile) { SeekerRecData results; RecommendResults recommendResults = null; // si el miembro cuenta con resultados anteriores, se le adicionan // los nuevos resultados boolean flag = recommendProfile.record.containsKey(seeker); if (flag) { //se obtienen los resultados de búsquedas anteriores del miembro results = recommendProfile.record.get(seeker); if (results.values.containsKey(query)) { recommendResults = results.values.get(query); Map<Integer, List<DocumentMetaData>> hash = list.getResultsMap(); recommendResults.insertRecommendation(hash); } else { recommendResults = recommendProfile.new RecommendResults(); results.values.put(query, recommendResults); } } else { // en caso de que el usuario no cuente recomendaciones previas, se // crea una nueva lista de recomendaciones y se le agregan los resultados obtenidos results = recommendProfile.new SeekerRecData(); recommendResults = recommendProfile.new RecommendResults(); Map<Integer, List<DocumentMetaData>> hash = list.getResultsMap(); Set<Integer> searchableEnum = hash.keySet(); for (Integer searcher : searchableEnum) { recommendResults.results.put(searcher, recommendProfile.new IndexRecommendation(hash.get(searcher))); } results.values.put(query, recommendResults); // se registra el miembro con los resultados obtenidos en la tabla // hash de los resultados de la búsquedas recommendProfile.record.put(seeker, results); } } /** * * Se recomienda un doc de un historial * */ private void collabSearchResults(final SessionProfile sessionProfile, final QuerySource querySource, final Seeker emitter, final String comments, final Documents docs, final Map<Seeker, ClientSidePrx> receptors) throws SessionException, SeekerException, RecommendationException, IOException, SQLException { // TODO: recomendar todos los resultados de ese usuario en esa sesión Thread thread = new Thread(new Runnable() { public void run() { try { String query = querySource.getQuery(); boolean storeSource = querySource.isStoreSource(); ResultSetMetaData doc = new ResultSetMetaData(); String sessionName = sessionProfile.getProperties().getSessionName(); if (storeSource) { //cache doc = getDocumentsList(docs); doc.setQuery(query); registerRecommendations(sessionProfile, emitter, new ArrayList<>(receptors.keySet()), doc, comments); notifyRecommendation(sessionName, emitter, receptors, comments, doc); } else { //BD final DataBaseController control = dbController; if (dbController.isOpen()) { //guardar final List<Integer> documents = docs.getIndexDocuments(); List<DocumentMetaData> metaDocs = dbController.getSearchResults(documents); doc.add(MULTIPLE_SEARCHERS, metaDocs); doc.setQuery(query); List<Seeker> seekers = new ArrayList<>(receptors.keySet()); registerRecommendations(sessionProfile, emitter, seekers, doc, comments); notifyRecommendation(sessionName, emitter, receptors, comments, doc); control.saveRecomendation(sessionProfile.getProperties().getSessionName(), emitter.getUser(), comments, documents, seekers); updateResultsStore(doc); } } } catch (SQLException ex) { OutputMonitor.printStream("SQL", ex); } catch (RecommendationException ex) { OutputMonitor.printStream("", ex); } } }); thread.start(); } }