All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.gdface.facelog.FuzzyMatchManagement Maven / Gradle / Ivy

There is a newer version: 5.3.0
Show newest version
package net.gdface.facelog;

import java.util.List;
import java.util.Map.Entry;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;

import gu.sql2java.IFuzzyMatchFilter.MatchErrorHandler;
import gu.sql2java.BaseBean;
import gu.sql2java.ColumnGetter;
import gu.sql2java.IStringMatchFilter;
import gu.sql2java.StringFieldSearcher;
import gu.sql2java.StringMatchType;
import gu.sql2java.TableManager;
import net.gdface.facelog.db.DeviceBean;
import net.gdface.facelog.db.DeviceGroupBean;
import net.gdface.facelog.db.IDeviceGroupManager;
import net.gdface.facelog.db.IPersonGroupManager;
import net.gdface.facelog.db.IDeviceManager;
import net.gdface.facelog.db.IPersonManager;
import net.gdface.facelog.db.PersonBean;
import net.gdface.facelog.db.PersonGroupBean;
import net.gdface.utils.BeanRelativeUtilits;
import net.gdface.utils.ConditionChecks;

import static net.gdface.facelog.db.Constant.FL_PERSON_ID_MOBILE_PHONE;
import static net.gdface.facelog.db.Constant.FL_PERSON_ID_PAPERS_NUM;

import static net.gdface.facelog.db.Constant.FL_DEVICE_ID_MAC;

/**
 * 模糊查询
 * @author guyadong
 *
 */
class FuzzyMatchManagement implements MatchErrorHandler,ServiceConstant{
	private final DaoManagement dm;
	/**
	 * 设备组模糊匹配对象
	 */
	private final GroupMatcher deviceGroupMatcher;
	/**
	 * 人员组模糊匹配对象
	 */
	private final GroupMatcher personGroupMatcher;
	/**
	 * 设备名字模糊匹配对象
	 */
	private final NameMatcher deviceNameMatcher;
	/**
	 * 设备MAC地址模糊匹配对象
	 */
	private final DeviceMacMatcher deviceMacMatcher;
	/**
	 * 人员名字模糊匹配对象
	 */
	private final NameMatcher personNameMatcher;
	/**
	 * 人员移动手机号模糊匹配对象
	 */
	private final PersonMobilePhoneMatcher mobilePhoneMatcher;
	/**
	 * 人员证件号码模糊匹配对象
	 */
	private final PersonPapersNumMatcher papersNumMatcher;
	FuzzyMatchManagement(DaoManagement dm) {
		this.dm = dm;
		this.deviceGroupMatcher = new GroupMatcher<>(IDeviceGroupManager.class);
		this.personGroupMatcher = new GroupMatcher<>(IPersonGroupManager.class);
		this.personNameMatcher = new NameMatcher<>(IPersonManager.class);
		this.deviceNameMatcher = new NameMatcher<>(IDeviceManager.class);
		
		this.mobilePhoneMatcher = new PersonMobilePhoneMatcher();
		this.papersNumMatcher = new PersonPapersNumMatcher();
		this.deviceMacMatcher = new DeviceMacMatcher();
	}
	
	FuzzyMatchManagement init(){
		logger.info("Device group fuzzy matcher initializing");
		deviceGroupMatcher.init();
		logger.info("Person group fuzzy matcher initializing");
		personGroupMatcher.init();
		logger.info("Device name fuzzy matcher initializing");
		deviceNameMatcher.init();
		logger.info("Device mac fuzzy matcher initializing");
		deviceMacMatcher.init();
		logger.info("Person name fuzzy matcher initializing");
		personNameMatcher.init();
		logger.info("Person mobile phone fuzzy matcher initializing");
		mobilePhoneMatcher.init();
		logger.info("Person papersnum matcher initializing");
		papersNumMatcher.init();

		return this;
	}
	/**
	 * 表字段模糊匹配查询
* 根据指定的匹配条件({@code pattern})对{@code tablename}指定的表字段模糊匹配
* 比如 '1102'匹配'1楼/1单元/102室'
* {@code column} 取值与{@code tablename}的值相关
*
	 *         tablename值       -- column可取值
	 *         fl_device            -- name,mac
	 *         fl_person           -- name,papsers_num,mobile_phone
	 *         fl_device_group -- 忽略
	 *         fl_person_group-- 忽略
	 * 
* {@code matchType}为{@code null}时,使用的默认匹配策略与{@code tablename}和{@code column}相关 *
	 *         tablename,column值--默认匹配策略
	 *         fl_device.name--支持通配符的字符串比较匹配{@link StringMatchType#WILDCARD_MATCH}
	 *         fl_device.mac--支持通配符的字符串比较匹配{@link StringMatchType#WILDCARD_MATCH}
	 *         fl_person.name--支持通配符的字符串比较匹配{@link StringMatchType#WILDCARD_MATCH}
	 *         fl_person.papsers_num--支持通配符的字符串比较匹配{@link StringMatchType#WILDCARD_MATCH}
	 *         fl_person.mobile_phone--数字模糊匹配{@link StringMatchType#DIGIT_FUZZY_MATCH}
	 *         fl_device_group--右侧数字模糊匹配{@link StringMatchType#DIGIT_FUZZY_RIGHT_MATCH}
	 *         fl_person_group--右侧数字模糊匹配{@link StringMatchType#DIGIT_FUZZY_RIGHT_MATCH}
	 * 
* @param tablename 表名,必须为'fl_device_group'或'fl_person_group','fl_device','fl_person' * @param column 指定模糊搜索的表字段名,可为{@code null}
* @param pattern 模糊匹配条件,如'102' * @param matchType 模糊匹配策略,为{@code null}使用默认值 * @param maxMatchCount 要求的最多匹配结果,如果返回的匹配结果超过此值则抛出异常,小于等于0时忽略 * @return 匹配结果列表,没有找到匹配记录时返回空表 * @throws FuzzyMatchCountExceedLimitException 返回的匹配结果超过{@code maxMatchCount} */ List fuzzySearch(String tablename,String column,String pattern, StringMatchType matchType, int maxMatchCount) throws FuzzyMatchCountExceedLimitException{ List matched; if(deviceNameMatcher.equals(column)){ if(deviceNameMatcher.getEffectColumnName().equals(column)){ matched = deviceNameMatcher.fuzzySearch(pattern, matchType == null ? null : matchType.createMatchFilter()); }else if(deviceMacMatcher.getEffectColumnName().equals(column)){ matched = deviceMacMatcher.fuzzySearch(pattern, matchType == null ? null : matchType.createMatchFilter()); }else{ throw new IllegalArgumentException("INVALID column " + column); } }else if(personNameMatcher.equals(column)){ if(personNameMatcher.getEffectColumnName().equals(column)){ matched = personNameMatcher.fuzzySearch(pattern, matchType == null ? null : matchType.createMatchFilter()); }else if(mobilePhoneMatcher.getEffectColumnName().equals(column)){ matched = mobilePhoneMatcher.fuzzySearch(pattern, matchType == null ? null : matchType.createMatchFilter()); }else if(papersNumMatcher.getEffectColumnName().equals(column)){ matched = papersNumMatcher.fuzzySearch(pattern, matchType == null ? null : matchType.createMatchFilter()); }else{ throw new IllegalArgumentException("INVALID column " + column); } }else if(deviceGroupMatcher.getTablename().equals(tablename)){ matched = deviceGroupMatcher.fuzzySearch(pattern, matchType == null ? null : matchType.createMatchFilter()); }else if(personGroupMatcher.getTablename().equals(tablename)){ matched = personGroupMatcher.fuzzySearch(pattern, matchType == null ? null : matchType.createMatchFilter()); }else if(deviceNameMatcher.getTablename().equals(tablename)){ matched = deviceNameMatcher.fuzzySearch(pattern, matchType == null ? null : matchType.createMatchFilter()); }else{ throw new IllegalArgumentException("INVALID tablename " + tablename); } ConditionChecks.checkTrue(maxMatchCount <= 0 || matched.size() <= maxMatchCount, FuzzyMatchCountExceedLimitException.class, "too manay match count %s, exceed max limit %s",matched.size(),maxMatchCount); return matched; } @Override public void onMatchError(Throwable e, String pattern) { logger.error("pattern={},{}:{}",pattern,e.getClass().getSimpleName(),e.getMessage()); } protected static class StringFieldSearcherForMatchEntry extends StringFieldSearcher{ public > StringFieldSearcherForMatchEntry(Class interfaceClass, String... effectColumnNames) { super(interfaceClass, effectColumnNames); } public > StringFieldSearcherForMatchEntry(Class interfaceClass, int... effectColumnId) { super(interfaceClass, effectColumnId); } public final List fuzzySearch(String pattern, IStringMatchFilter matchFilter){ Multimap mm = super.search(pattern, matchFilter); List entrys = Lists.newArrayList(); for(Entry entry:mm.entries()){ entrys.add(new MatchEntry(entry.getValue(), entry.getKey())); } // 按匹配的名字排序 return BeanRelativeUtilits.sortByField(entrys, "key"); } } /** * 设备组/人员组路径模糊匹配对象
* 默认使用'右侧数字模糊匹配'匹配策略 * @author guyadong * * @param 表记录类型 * @param 表访问实例类型 */ private class GroupMatcher > extends StringFieldSearcherForMatchEntry{ public GroupMatcher(Class interfaceClass) { super(interfaceClass, "name","parent"); setDefaultMatchFilter(StringMatchType.DIGIT_FUZZY_RIGHT_MATCH); setFunKeyGetter(new GroupPathGetter<>(interfaceClass)); setErrorHandler(FuzzyMatchManagement.this); } } /** * 设备/人员名字{@code name}字段模糊匹配对象
* 默认使用'支持通配符的字符串比较匹配'匹配策略 * @author guyadong * * @param 表记录类型 * @param 表访问实例类型 */ private class NameMatcher > extends StringFieldSearcherForMatchEntry{ @SuppressWarnings("unchecked") public NameMatcher(Class interfaceClass) { super(interfaceClass, "name"); setDefaultMatchFilter(StringMatchType.WILDCARD_MATCH); setFunKeyGetter((Function) new ColumnGetter("name")); setErrorHandler(FuzzyMatchManagement.this); } } private class PersonMobilePhoneMatcher extends StringFieldSearcherForMatchEntry{ @SuppressWarnings("unchecked") public PersonMobilePhoneMatcher() { super(IPersonManager.class, FL_PERSON_ID_MOBILE_PHONE); setDefaultMatchFilter(StringMatchType.DIGIT_FUZZY_MATCH); Function f = new ColumnGetter(FL_PERSON_ID_MOBILE_PHONE); setFunKeyGetter((Function) f); setErrorHandler(FuzzyMatchManagement.this); } } private class PersonPapersNumMatcher extends StringFieldSearcherForMatchEntry{ @SuppressWarnings("unchecked") public PersonPapersNumMatcher() { super(IPersonManager.class, FL_PERSON_ID_PAPERS_NUM); setDefaultMatchFilter(StringMatchType.WILDCARD_MATCH); Function f = new ColumnGetter(FL_PERSON_ID_PAPERS_NUM); setFunKeyGetter((Function) f); setErrorHandler(FuzzyMatchManagement.this); } } private class DeviceMacMatcher extends StringFieldSearcherForMatchEntry{ @SuppressWarnings("unchecked") public DeviceMacMatcher() { super(IDeviceManager.class, FL_DEVICE_ID_MAC); setDefaultMatchFilter(StringMatchType.WILDCARD_MATCH); Function f = new ColumnGetter(FL_DEVICE_ID_MAC); setFunKeyGetter((Function) f); setErrorHandler(FuzzyMatchManagement.this); } } private class GroupPathGetter> implements Function{ private final Class interfaceClass; public GroupPathGetter(Class interfaceClass) { this.interfaceClass = interfaceClass; } @Override public String apply(B input) { return dm.daoGroupPathOf(interfaceClass,input); } } }