/* * Copyright 2013 Research Studios Austria Forschungsgesellschaft mBH * * This file is part of easyrec. * * easyrec is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * easyrec is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with easyrec. If not, see <http://www.gnu.org/licenses/>. */ package org.easyrec.plugin.profileduke.duke.matchers; import no.priv.garshol.duke.Record; import no.priv.garshol.duke.matchers.AbstractMatchListener; import org.easyrec.model.core.ItemAssocVO; import org.easyrec.model.core.ItemVO; import org.easyrec.plugin.profileduke.ProfileDukeGenerator; import org.easyrec.service.core.ItemAssocService; import java.util.*; /** * ProfileDuke Plugin. <p/> <p><b>Company: </b> SAT, * Research Studios Austria</p> <p><b>Copyright: </b> (c) 2012</p> <p><b>last modified:</b><br/> $Author$<br/> * $Date$<br/> $Revision$</p> * * @author Soheil Khosravipour * @author Fabian Salcher */ public class EasyrecProfileMatcher extends AbstractMatchListener { private int numberOfCreatedAssociations = 0; private int numberOfMatches = 0; private int numberOfMaybeMatches = 0; private int records = 0; private int nonmatches; // only counted in record linkage mode private boolean createAssociationsFromMaybeMatches; private boolean linkage; // means there's a separate indexing step private List<ItemVO<Integer, Integer>> items; private static Integer confTanantId; private Integer sourceType; private Integer viewType; private static Integer assocType; private ArrayList<ItemAssocVO<Integer, Integer>> itemAssocArrayList; private ItemAssocService itemAssocService; private ProfileDukeGenerator profileDukeGenerator; private HashMap<Integer, HashMap<Integer, Double>> userToUsers = new HashMap<Integer, HashMap<Integer, Double>>(); public void setItemAssocHashMap(HashMap<Integer, HashMap<Integer, Double>> userToUsers) { this.userToUsers = userToUsers; } public HashMap<Integer, HashMap<Integer, Double>> getItemAssocHashMap() { return userToUsers; } public void setItemAssocService(ItemAssocService itemAssocService) { this.itemAssocService = itemAssocService; } public void setConfTanantId(Integer confTanantId) { this.confTanantId = confTanantId; } public void setAssocType(Integer assocType) { this.assocType = assocType; } public void setSourceType(Integer sourceType) { this.sourceType = sourceType; } public void setViewType(Integer viewType) { this.viewType = viewType; } public void setItemAssocArrayList(ArrayList<ItemAssocVO<Integer, Integer>> itemAssocArrayList) { this.itemAssocArrayList = itemAssocArrayList; } public EasyrecProfileMatcher(boolean createAssociationsFromMaybeMatches, boolean linkage, ProfileDukeGenerator profileDukeGenerator) { this.createAssociationsFromMaybeMatches = createAssociationsFromMaybeMatches; this.linkage = linkage; this.profileDukeGenerator = profileDukeGenerator; } public int getMatchCount() { return numberOfMatches; } public void batchReady(int size) { if (linkage) records += size; // no endRecord() call in linkage mode ProfileDukeGenerator.logger.info("Records: " + records); } public void matches(Record r1, Record r2, double confidence) { numberOfMatches++; createAssociationBetweenRecords(r1, r2, confidence); } public void matchesPerhaps(Record r1, Record r2, double confidence) { numberOfMaybeMatches++; if (createAssociationsFromMaybeMatches) createAssociationBetweenRecords(r1, r2, confidence); } public void endRecord() { records++; } public void endProcessing() { ProfileDukeGenerator.logger.info(""); ProfileDukeGenerator.logger.info("Total records: " + records); ProfileDukeGenerator.logger.info("Total matches: " + numberOfMatches); ProfileDukeGenerator.logger.info("Maybe matches: " + numberOfMaybeMatches); if (nonmatches > 0) // FIXME: this ain't right. we should know the mode ProfileDukeGenerator.logger.info("Total non-matches: " + nonmatches); profileDukeGenerator.setNumberOfAssociationsCreated(numberOfCreatedAssociations); } public void noMatchFor(Record record) { nonmatches++; } /** * Creates an association and saves it in the DB. * * @param r1 first record which represents an item * @param r2 second record which represents an item * @param confidence associationValue */ public void createAssociationBetweenRecords(Record r1, Record r2, double confidence) { Date execution = new Date(); ItemAssocVO<Integer, Integer> itemAssoc = new ItemAssocVO<Integer, Integer>( confTanantId, new ItemVO(profileDukeGenerator.getTenantId(), r1.getValue("ItemID"), profileDukeGenerator.getItemType()), assocType, confidence, new ItemVO(profileDukeGenerator.getTenantId(), r2.getValue("ItemID"), profileDukeGenerator.getItemType()), sourceType, "ProfileDuke Plugin", viewType, null, execution); numberOfCreatedAssociations++; itemAssocService.insertOrUpdateItemAssoc(itemAssoc); } public static String toString(Record r) { StringBuffer buf = new StringBuffer(); for (String p : r.getProperties()) { Collection<String> vs = r.getValues(p); if (vs == null) continue; buf.append(p + ": "); for (String v : vs) buf.append("'" + v + "', "); } //buf.append(";;; " + r); return buf.toString(); } }