educoder/project_match/src/main/java/com/ossean/util/MergeProjectsUtil.java

1101 lines
39 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.ossean.util;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;
import com.ossean.databaseDest.DBDest;
import com.ossean.databaseSource.DBSource;
import com.ossean.databaseSource.GatherDao;
import com.ossean.model.EddRelations;
import com.ossean.model.GatherProjectsModel;
import com.ossean.model.Synonymmings;
import com.ossean.model.Synonyms;
import com.ossean.model.Taggings;
import com.ossean.model.Tags;
@Component("mergeProjectsUtil")
public class MergeProjectsUtil {
Logger logger = Logger.getLogger(this.getClass());
@Resource
private DBSource dbSource;
@Resource
private GatherDao gatherDao;
@Resource
private DBDest dbDest;
@Qualifier("gatherProjectsUtil")
@Autowired
private GatherProjectsUtil gatherProjectsUtil;
private String synonymTableName = "synonyms";
private String synonymmingTableName = "synonymmings";
private String gatherProjectsTableName = "gather_projects";
private String pointerTableName = "edd_pointers";
private String taggingsTableName = "taggings";
private String tagsTableName = "tags";
private String eddRelationTableName = "edd_relations";
//判断两个项目是否相同 默认两个项目的urlMD5码是不同的
public boolean areTwoProjectsTheSame(GatherProjectsModel model1, GatherProjectsModel model2){
/**
* 如果是同一个社区 则默认不相同
*/
if(model1.getSource().equals(model2.getSource()))
return false;
boolean result = false;
//两个项目初步匹配结果是相同的
boolean stepOneResult = false;
result = isTheSameAfterTFIDF(model1, model2, stepOneResult);
return result;
}
//edd算法提取linkNames 其中包含项目名本身
public List<String> getSynonyms(GatherProjectsModel model){
model.setName(model.getName().trim());
model.setDescription(model.getDescription().trim());
List<String> result = dbSource.getSynonyms(synonymTableName, synonymmingTableName, model.getId());//表示当前的项目已经处理过了 当前的是需要更新的
if(result.size() != 0){
for(String s : result){
logger.info("gather_project:" + model.getId() + " gets synonyms:" + s + " in table");
}
return result; //表示当前项目的别名在数据库中已经存在了
}
String description = model.getDescription();
if(description == null)
return result;
Map<String,Integer> linkNames = new HashMap<String,Integer>();//用于存储所有提取出来的关联项目名
//对项目名进行处理
//提取项目名中去除公司名或基金组织的信息
String projectNameWithoutComName = StringHandler_ProjectName.getProjectWithoutComName(model.getName());
if(!"".equals(projectNameWithoutComName)){
//表示匹配到了相应公司或基金委的项目
linkNames.put(projectNameWithoutComName, 1);
}
//提取项目名括号中的信息
String bracket = StringHandler_ProjectName.getBracket(model.getName());
if(!"".equals(bracket)){
//去除括号中信息的特殊符号
bracket = RegexHandler.extractEngDecChiAndDot(bracket);
if(!RegexHandler.onlySpecialChar(bracket)){
System.out.println("项目括号中的信息: "+bracket);
linkNames.put(bracket, 1);
}
}
//读取be动词表
List<String> beWords = FileReader.read("./files/beVerb.txt");
description = StringHandler.getFirstSentence(description);
for(String beWord:beWords){
//按系动词表优先级进行匹配
String linkName = StringHandler.findLinkName(description, beWord);
System.out.println("desc be动词之前的 "+linkName);
if(linkName == null){
//表示没有匹配到当前的系动词 进行下一个匹配
continue;
}
//特征短语去噪
//提取主副描述信息(括号中)
List<String> linkNameResult = EDDHandler.getMainAndViceDescriptionByBracket(linkName);
//提取主副描述信息(known as+连词)
linkNameResult = EDDHandler.getMainAndViceDescriptionByKnowAs(linkNameResult);
//去除定语描述信息(逗号定语)
linkNameResult = EDDHandler.removeComma(linkNameResult);
//去除定语描述信息(定冠词The)
linkNameResult = EDDHandler.removeDemonstrativeWords(linkNameResult);
//去除从句描述信息
linkNameResult = EDDHandler.removeArrtibutiveClause(linkNameResult);
//去除指示代词
linkNameResult = EDDHandler.removePronoun(linkNameResult);
//去除项目常用词
linkNameResult = EDDHandler.removeProject(linkNameResult);
//去除指示代词和项目常用词两者的笛卡尔积
linkNameResult = EDDHandler.removePPCombine(linkNameResult);
// //特殊字符处理(空字符串)
// linkNameResult = EDDHandler.removeEmpty(linkNameResult);
// //特殊字符处理(引号)
// linkNameResult = EDDHandler.removeSemicolon(linkNameResult);
// 特殊字符处理(除英文中文外 中间用空格连接)
// linkNameResult = EDDHandler.removeSingleColon(linkNameResult);
//提取项目中
linkNameResult = RegexHandler.extractEngDecChiAndDot(linkNameResult);
//删除只有特殊字符的同义词
linkNameResult = RegexHandler.removeOnlySpecial(linkNameResult);
for(String name:linkNameResult){
if(linkNames.containsKey(name)){
linkNames.put(name, linkNames.get(name)+1);
}else{
if(!name.equals(model.getName().toLowerCase()))
linkNames.put(name, 1);
}
}
break;
}//遍历be动词 for循环结尾
//将map转换成List
Set<String> keys = linkNames.keySet();
Iterator<String> it = keys.iterator();
while(it.hasNext()){
String a = it.next();
result.add(a);
System.out.println("result中包含的 "+a);
}
/**
* 对上面提取出来的同义词结果进行进一步限制 返回结果为result3
*/
List<String> result2 = new ArrayList<String>();
//若项目名为缩写形式 项目描述信息中存不存在项目名的全称
String fullName = StringHandler.getFullName(model.getName().toLowerCase(), result);
if(!fullName.equals("")){
result2.add(fullName.toLowerCase());//表示项目名确实是缩写 并提取到了项目全名
System.out.println("项目的全称为: "+fullName);
}
String shortName = StringHandler.getShortName(model.getName().toLowerCase(), result);
if(!shortName.equals("")){
result2.add(shortName.toLowerCase());//表示项目名确实是全称 并提取到了项目缩写
System.out.println("项目的简称为: "+shortName);
}
//要求描述信息中出现的项目名对应的词 按照顺序链接到一起
for(int i = 0; i < result.size(); i++){
//同义词要在项目名中出现
String extract = "";
String synonym = result.get(i);
String[] words = synonym.split(" ");//按照空格进行分词
//去掉括号检测同义词是否在项目名中出现
String modelNameWithoutBracket = StringHandler_ProjectName.removeBracket(model.getName().toLowerCase());
System.out.println("modelNameWithoutBracket : "+modelNameWithoutBracket);
for(String word:words){
//查看每个词在项目名中是否出现
if(modelNameWithoutBracket.indexOf(word) >= 0){
//表示项目名中存在这个分词
extract += word + " ";
}
}
if(!"".equals(extract)){
//表示确实是别名
extract = extract.substring(0, extract.length() - 1);
System.out.println("别名在项目名中有出现: "+extract);
result2.add(extract);
continue;
}
}
//对最终结果进行处理:如果与项目原名相同:去除 如果提取出了相同的结果:去除重复的
Map<String,Integer> tmp = new HashMap<String,Integer>();
for(String r:result2){
r = r.toLowerCase();
if(!r.equals(model.getName().toLowerCase()))
tmp.put(r, 1);
}
//将map中的key转换为list
List<String> result3 = new ArrayList<String>();
Set<String> keys_tmp = tmp.keySet();
Iterator it_tmp = keys_tmp.iterator();
while(it_tmp.hasNext())
result3.add(it_tmp.next().toString());
result3.add(model.getName().toLowerCase());
//项目同义词不包括项目原名
//输出日志文件
for(String s : result3){
logger.info("gather_project:" + model.getId() + " gets synonyms:" + s + " by description");
}
return result3;
}
//根据项目别名判断两个项目初步匹配是否正确 返回值为匹配上的项目别名
public boolean isTheSameByLinkName(List<String> linkNames1, List<String> linkNames2){
//对两个项目的别名之间进行匹配
for(int i = 0; i < linkNames1.size(); i++){
String linkName1 = linkNames1.get(i);
for(int j = 0; j < linkNames2.size(); j++){
String linkName2 = linkNames2.get(j);
if(linkName1.equals(linkName2))
return true;
}
}
return false;
}
//去伪取真过程
public boolean isTheSameAfterTFIDF(GatherProjectsModel model1, GatherProjectsModel model2, boolean stepOneResult){
//获取两个对象的tags属性
String tags1 = model1.getTags();
String tags2 = model2.getTags();
if((tags1 != null && tags2 != null)&&(!"".equals(tags1) && !"".equals(tags2))){
//表示两个项目都有标签
double similarity = calSimilarityByTag(model1, model2);
System.out.println("calSimilarityByTag"+String.valueOf(similarity));
if(stepOneResult){
//表示两个项目源自一个社区 去伪
//如果两个项目匹配结果 weight>0.9 表示是同一个项目
if(similarity > 0.9)
return true;
return false;
}else{
//表示两个项目不来自同一个社区 存真
//如果两个项目匹配结果 weight<0.1 表示不是同一个项目
if(similarity < 0.1)
return false;
return true;
}
}
else{
if((tags1 == null && tags2 != null) || ("".equals(tags1) && !"".equals(tags2)) || (!"".equals(tags1) && "".equals(tags2)) || (tags1 != null && tags2 == null)){
//表示两者有一个项目有标签
Map<String, Integer> result = new HashMap<String, Integer>();
List<String> tagList = new ArrayList<String>();
int count_tag = 0;
if(tags1 == null){
//表示项目2有标签
//对项目1的描述信息进行分词
result = getResolveResult(model1.getDescription());
String[] tmp = tags2.split(",");
count_tag = tmp.length;
tagList = changeArrayToList(tmp);
}else{
//表示项目1有标签
result = getResolveResult(model2.getDescription());
String[] tmp = tags1.split(",");
count_tag = tmp.length;
tagList = changeArrayToList(tmp);
}
if(stepOneResult){
//表示两个项目来自同一社区 匹配上的标签数量应该在50%以上
int threshold = 0;
if(count_tag % 2 == 0)
threshold = count_tag / 2;
else
threshold = count_tag / 2 + 1;
int count_match = matchListAndMap(tagList,result);
if(count_match >= threshold)
return true;
else
return false;
}else{
int threshold = 1;
int count_match = matchListAndMap(tagList, result);
if(count_match >= threshold)
return true;
else
return false;
}
}else{
//表示两者都没有标签
double similarity = calSimilarityByDescription(model1, model2);
if(stepOneResult){
//表示两个项目源自一个社区 去伪
//如果两个项目匹配结果 weight>0.9 表示是同一个项目
if(similarity > 0.9)
return true;
return false;
}else{
//表示两个项目不来自同一个社区 存真
//如果两个项目匹配结果 weight<0.1 表示不是同一个项目
if(similarity < 0.1)
return false;
return true;
}
}
}
}
//计算都有标签的项目之间的相似度
public double calSimilarityByTag(GatherProjectsModel model1, GatherProjectsModel model2){
// 读取item_tag_relation表中项目总数
// int wholeNum = dbSource.getItemNumber(taggingsTableName, "OpenSourceProject");
// 读取item_tag_relation表中该model对应的标签对象
// List<Taggings> taggingsList1 = dbSource.getTaggingsListByTaggableId(taggingsTableName, model1.getId());
// List<Taggings> taggingsList2 = dbSource.getTaggingsListByTaggableId(taggingsTableName, model2.getId());
//
// //读取每个name对应的tag对象
// List<Tags> tagList1 = getTagListByItemTagRelationList(taggingsList1);
// List<Tags> tagList2 = getTagListByItemTagRelationList(taggingsList2);
//获取权重向量
// Map<Integer, List<Double>> weightListMap = getWeightVectorByTag(tagList1, tagList2, wholeNum);
// List<Double> weightVector1 = weightListMap.get(1);
// List<Double> weightVector2 = weightListMap.get(2);
// return calDistance(weightVector1, weightVector2);
String[] tagArray_model1 = model1.getTags().split(",");
String[] tagArray_model2 = model2.getTags().split(",");
List<String> tags_model1 = changeArrayToList(tagArray_model1);
List<String> tags_model2 = changeArrayToList(tagArray_model2);
//比较两个list中相同标签的个数
List<String> sameTags = getSameStringsInList(tags_model1, tags_model2);
int minNum_tag = tags_model1.size() < tags_model2.size() ? tags_model1.size() : tags_model2.size();
float sameRate = (float)(sameTags.size() * 1.0 / minNum_tag);
System.out.println("same rate between teo tags : "+sameRate);
return sameRate;
}
//计算文本相似度
public double calSimilarityByDescription(GatherProjectsModel model1, GatherProjectsModel model2){
long time4_1 = System.currentTimeMillis();
String description1 = model1.getDescription();
String description2 = model2.getDescription();
Map<String, Integer> resolveResult1 = getResolveResult(description1);
Map<String, Integer> resolveResult2 = getResolveResult(description2);
Map<String, Double> tfResult1 = calTFOfDescription(resolveResult1);
Map<String, Double> tfResult2 = calTFOfDescription(resolveResult2);
Map<String, Double> idfResult = calIDFOfDescription(resolveResult1, resolveResult2);
List<String> commonList = new ArrayList<String>();
List<String> uniqueList1 = new ArrayList<String>();
List<String> uniqueList2 = new ArrayList<String>();
Set<String> keys1 = resolveResult1.keySet();
Iterator<String> it1 = keys1.iterator();
while(it1.hasNext()){
String key1 = it1.next();
if(resolveResult2.containsKey(key1)){
commonList.add(key1);
}else{
uniqueList1.add(key1);
}
}
Set<String> keys2 = resolveResult2.keySet();
Iterator<String> it2 = keys2.iterator();
while(it2.hasNext()){
String key1 = it2.next();
if(resolveResult1.containsKey(key1)){
//因为遍历第一个map时已经将commonList进行构造了 此处不用再add了
}else{
uniqueList2.add(key1);
}
}
List<Double> weightCommon1 = calWeightListOfDescription(commonList, tfResult1, idfResult);
List<Double> weightCommon2 = calWeightListOfDescription(commonList, tfResult2, idfResult);
List<Double> weightUnique1 = calWeightListOfDescription(uniqueList1, tfResult1, idfResult);
List<Double> weightUnique2 = calWeightListOfDescription(uniqueList2, tfResult2, idfResult);
List<Double> weightResult1 = new ArrayList<Double>();
List<Double> weightResult2 = new ArrayList<Double>();
for(int i = 0; i < weightCommon1.size(); i++){
weightResult1.add(weightCommon1.get(i));
weightResult2.add(weightCommon2.get(i));
}
for(int i = 0; i < weightUnique1.size(); i++){
weightResult1.add(weightUnique1.get(i));
weightResult2.add(0.0);
}
for(int i = 0; i < weightUnique2.size(); i++){
weightResult1.add(0.0);
weightResult2.add(weightUnique2.get(i));
}
long time4_2 = System.currentTimeMillis();
if(time4_2 - time4_1 > 10)
logger.info("time cost for cal similarity by description: " + (time4_2 - time4_1));
return calDistance(weightResult1, weightResult2);
}
//找两个向量组成的相似向量
public Map<Integer, List<Double>> getWeightVectorByTag(List<Tags> tagList1, List<Tags> tagList2, int wholeNum){
long time5_1 = System.currentTimeMillis();
List<Tags> commonTagList1 = new ArrayList<Tags>();//里面用Tag表示格式不同的相同标签 在取得时候两者都要取出来
List<Tags> commonTagList2 = new ArrayList<Tags>();
List<Tags> uniqueTag1 = new ArrayList<Tags>();
List<Tags> uniqueTag2 = new ArrayList<Tags>();
//首先要根据两边的tag组成向量
for(int i = 0; i < tagList1.size(); i++){
Tags tag1 = tagList1.get(i);
Tags similarTag;
if((similarTag = theMostSimilarTag(tag1, tagList2)) != null){
//表示存在相同的标签
commonTagList1.add(tag1);
commonTagList2.add(similarTag);
}
}
//找到各自独有的标签
uniqueTag1 = findUniqueTag(tagList1, commonTagList1);
uniqueTag2 = findUniqueTag(tagList2, commonTagList2);
List<Double> weightList1 = new ArrayList<Double>();
List<Double> weightList2 = new ArrayList<Double>();
for(int i = 0; i < commonTagList1.size(); i++){
Tags tag1 = commonTagList1.get(i);
Tags tag2 = commonTagList2.get(i);
double weight = calIDFOfTag(tag1, tag2, wholeNum);
weightList1.add(weight);
weightList2.add(weight);
}
for(int i = 0; i < uniqueTag1.size(); i++){
Tags tag1 = uniqueTag1.get(i);
double weight = calIDFOfTag(tag1, wholeNum);
weightList1.add(weight);
weightList2.add(0.0);
}
for(int i = 0; i < uniqueTag2.size(); i++){
Tags tag2 = uniqueTag2.get(i);
double weight = calIDFOfTag(tag2, wholeNum);
weightList2.add(weight);
weightList1.add(0.0);
}
Map<Integer, List<Double>> result = new HashMap<Integer, List<Double>>();
result.put(1, weightList1);
result.put(2, weightList2);
long time5_2 = System.currentTimeMillis();
if(time5_2 - time5_1 > 10)
logger.info("time cost for get weight vector by tag: " + (time5_2 - time5_1));
return result;
}
//找List各自独有的标签
public List<Tags> findUniqueTag(List<Tags> tagList, List<Tags> commonList){
List<Tags> result = new ArrayList<Tags>();
for(Tags tag:tagList){
if(!isExist(tag, commonList)){
//表示独有
result.add(tag);
}
}
return result;
}
//判断后者是否拥有前者
public boolean isExist(Tags tag, List<Tags> list){
for(Tags t:list){
if(tag.getId() == t.getId())
return true;
}
return false;
}
//找与该标签最相似的标签
public Tags theMostSimilarTag(Tags tag, List<Tags> tagList){
if(tag == null)
return null;
//对标签进行特殊字符去除处理
String tagName = RegexHandler.extractEngDecimalAndChinese(tag.getName());
for(Tags t:tagList){
if(t == null)
continue;
String tName = RegexHandler.extractEngDecimalAndChinese(t.getName());
if(tagName.equals(tName)){
//表示两个标签完全相同
return t;
}
}
return null;//表示没有找到相同的标签
}
public String theMostSimilarString(String str, List<String> strList){
if(str == null)
return null;
for(String s : strList){
if(s == null)
continue;
if(s.equals(str)){
//表示两个str相同
return str;
}
}
return null;
}
//计算tag对应id的idf值
public double calIDFOfTag(Tags tag1, Tags tag2, int wholeNum){
double result = 0.00;
int count = dbSource.getNumOfTagIdAndOspByTwoTagIds(taggingsTableName, tag1.getId(), tag2.getId());
result = wholeNum * 1.0 / count;
result = Math.log(result);
return result;
}
//上面函数的重载
public double calIDFOfTag(Tags tag, int wholeNum){
double result = 0.00;
int count = dbSource.getNumOfTagIdAndOsp(taggingsTableName, tag.getId());
result = wholeNum * 1.0 / count + 0.0001;
result = Math.log(result);
return result;
}
//根据itemTagRelationList找到对应tag_id的Tag对象列表
public List<Tags> getTagListByItemTagRelationList(List<Taggings> itemTagRelationList){
List<Tags> result = new ArrayList<Tags>();
for(Taggings i:itemTagRelationList){
Tags t = dbSource.getTagById(tagsTableName, i.getTag_id());
result.add(t);
}
return result;
}
//计算向量余弦夹角
public double calDistance(List<Double> vector1, List<Double> vector2){
double numerator = 0.0;//分子
double denominator = 0.0001;//分母
numerator = calNumerator(vector1, vector2);
denominator = calDenominator(vector1, vector2);
return numerator / denominator;
}
//余弦夹角分子计算
public double calNumerator(List<Double> vector1, List<Double> vector2){
Double result = 0.0;
for(int i = 0; i < vector1.size(); i++){
result += vector1.get(i) * vector2.get(i);
}
return result;
}
//余弦夹角分母计算
public double calDenominator(List<Double> vector1, List<Double> vector2){
Double result = 0.0001;
double result1 = 0.0;
for(Double d:vector1){
result1 += d * d;
}
result1 = Math.sqrt(result1);
double result2 = 0.0;
for(Double d:vector2){
result2 += d * d;
}
result2 = Math.sqrt(result2);
result = result1 * result2;
return result;
}
//对描述信息进行分词得到词频统计结果的Map
public Map<String, Integer> getResolveResult(String description){
long time6_1 = System.currentTimeMillis();
Map<String, Integer> result = new HashMap<String, Integer>();
Reader text = new StringReader(description);
IKSegmenter ik = new IKSegmenter(text, true);
Lexeme term = null;
try {
//处理一个分词结果
while((term = ik.next()) != null){
String tmp = term.getLexemeText().toString();
tmp = RegexHandler.extractEngDecimalAndChinese(tmp).toLowerCase();
if(result.containsKey(tmp))
result.put(tmp, result.get(tmp) + 1);
else
result.put(tmp, 1);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long time6_2 = System.currentTimeMillis();
if(time6_2 - time6_1 > 10)
logger.info("time cost for get resolve result: " + (time6_2 - time6_1));
return result;
}
//计算文本匹配tf值
public Map<String, Double> calTFOfDescription(Map<String, Integer> map){
long time7_1 = System.currentTimeMillis();
Map<String, Double> result = new HashMap<String, Double>();
Set<String> keys = map.keySet();
Iterator<String> it = keys.iterator();
int tfAll = 0;
//计算当前描述所有词词频总和
while(it.hasNext()){
String name = it.next();
tfAll += map.get(name);
}
Iterator<String> it2 = keys.iterator();
while(it2.hasNext()){
String name = it2.next();
int tf = map.get(name);
double weight = tf * 1.0 / tfAll;
result.put(name, weight);
}
long time7_2 = System.currentTimeMillis();
if(time7_2 - time7_1 > 10)
logger.info("time cost for cal tf of description: " + (time7_2 - time7_1));
return result;
}
//计算文本匹配IDF值
public Map<String, Double> calIDFOfDescription(Map<String, Integer> map1, Map<String, Integer> map2){
long time8_1 = System.currentTimeMillis();
int docNum = 2;
Map<String, Double> result = new HashMap<String, Double>();
Map<String, Integer> count_n = new HashMap<String, Integer>();
Set<String> keys1 = map1.keySet();
Iterator<String> it1 = keys1.iterator();
while(it1.hasNext()){
String key = it1.next();
if(count_n.containsKey(key)){
count_n.put(key, count_n.get(key) + 1);
}else{
count_n.put(key, 1);
}
}
Set<String> keys2 = map2.keySet();
Iterator<String> it2 = keys2.iterator();
while(it2.hasNext()){
String key = it2.next();
if(count_n.containsKey(key)){
count_n.put(key, count_n.get(key) + 1);
}else{
count_n.put(key, 1);
}
}
Set<String> keys = count_n.keySet();
Iterator<String> it = keys.iterator();
while(it.hasNext()){
String name = it.next();
double weight = docNum / count_n.get(name) * 1.0 + 0.0001;
weight = Math.log(weight);
result.put(name, weight);
}
long time8_2 = System.currentTimeMillis();
if(time8_2 - time8_1 > 10)
logger.info("time cost for cal idf of description: " + (time8_2 - time8_1));
return result;
}
//根据文本的list得到weight的list
public List<Double> calWeightListOfDescription(List<String> textList, Map<String, Double> tfMap, Map<String, Double> idfMap){
long time9_1 = System.currentTimeMillis();
List<Double> result = new ArrayList<Double>();
for(int i = 0; i < textList.size(); i++){
double weight = tfMap.get(textList.get(i)) * idfMap.get(textList.get(i));
result.add(weight);
}
long time9_2 = System.currentTimeMillis();
if(time9_2 - time9_1 > 10)
logger.info("time cost for cal weight list of description: " + (time9_2 - time9_1));
return result;
}
//将linkNames存入数据库
public void insertSynonyms(List<String> linkNames){
for(String name:linkNames){
Synonyms model = new Synonyms();
model.setName(name.trim());
dbSource.insertSynonym(synonymTableName, model);
}
}
//插入数据到同义词表和项目关联表
public void insertSynonymming(List<String> linkNames, int synonymming_id){
for(String name:linkNames){
//查找同义词对象
Synonyms synonyms = dbSource.getSynonymByName(synonymTableName, name);
//如果synonyms漏掉 没有加入到数据库 则不执行后面的操作
if(synonyms == null)
continue;
Synonymmings synonymmings = new Synonymmings();
synonymmings.setSynonym_id(synonyms.getId());
synonymmings.setSynonymming_id(synonymming_id);
try {
dbSource.insertSynonymming(synonymmingTableName, synonymmings);
logger.info("project:" + synonymming_id + " has synonym:" + synonyms.getName());
} catch (Exception e) {
//在插入同义词时 gather_projects中的记录已经被删除掉了
logger.info("gather_projects_id has been removed");
break;
}
}
}
//匹配完成后 将关联上的项目进行合并 结果存储到edd_relations表中 最后一个参数为true表示是更新表中的数据
public void handleAfterMatch(GatherProjectsModel model, List<String> synonyms, List<GatherProjectsModel> matchedProjectList, boolean updateOrNot){
insertSynonyms(synonyms);//插入新增项目的同义词
insertSynonymming(synonyms, model.getId());//插入新增项目和同义词之间的关联
//处理同义词表
for(int i = 0; i < matchedProjectList.size(); i++){
GatherProjectsModel model1 = matchedProjectList.get(i);
List<String> synonyms_1 = getSynonyms(model1);//获取同义词
//判断两个项目是不是来自同一个社区 如果是则不插入彼此的同义词
if(!((""+model.getSource()).equals(model1.getSource()+""))){
logger.info("project:" + model.getId() + " and project:" + model1.getId() + " add synonyms after match");
insertSynonymming(synonyms_1, model.getId());//在新增项目中插入关联项目同义词记录
insertSynonymming(synonyms, model1.getId());//在关联项目中插入新增项目的同义词记录
}
}
List<EddRelations> relationsList = new ArrayList<EddRelations>();
EddRelations relation_model = new EddRelations();
relation_model.setGather_projects_ids(","+model.getId()+",");
relationsList.add(relation_model); //relationsList用于记录包含当前项目在内的
List<EddRelations> relationsList_matched = new ArrayList<EddRelations>();//匹配上的项目在edd_relations表中的记录
for(int i = 0; i < matchedProjectList.size(); i++){
GatherProjectsModel model2 = matchedProjectList.get(i);
//查找edd_relations表得到相应的记录
List<EddRelations> eddRelationList = dbSource.getEddRelationsByGatherProjectsId(eddRelationTableName, model2.getId());
for(EddRelations relation:eddRelationList){
relationsList.add(relation);
relationsList_matched.add(relation);
}
if(eddRelationList.size() == 0){
//表示之前没有匹配上项目的匹配记录 需要插入这条记录 eg: ,12,
EddRelations relation = new EddRelations();
relation.setGather_projects_ids(","+model2.getId()+",");
relationsList.add(relation); //relationsList用于记录包含当前项目在内的
}
}
//relationsList_now表示目前正在处理的项目在edd_relations表中的记录 需要在插入新的edd_relations对象前查找
List<EddRelations> relationsList_now = dbSource.getEddRelationsByGatherProjectsId(eddRelationTableName, model.getId());
//统计relationList中所有不同的gather_projects_id
String relation_new_gather_projects_ids = hasDiffProjFromSameCommunity(relationsList);
EddRelations eddRelation = new EddRelations();
if(relation_new_gather_projects_ids != null){
//表示匹配结果中不存在同一个社区不同的多个项目匹配到一起
eddRelation.setGather_projects_ids(relation_new_gather_projects_ids);
dbSource.insertEddRelations(eddRelationTableName, eddRelation);//插入最新的结果集
/**
* 删除关联项目在edd_relations表中对应的记录
*/
for(EddRelations relation:relationsList_matched)
deleteExistEddRelations(relation);
/**
* 如果是更新项目 需要查看edd_relations表中是否有该记录 如果有要删除掉
*/
for(EddRelations relation:relationsList_now)
deleteExistEddRelations(relation);
}else{
//表示结果有来自同一社区的项目 如果当前项目在edd_relations表中找不到相应记录 则应插入本身的记录;反之不进行操作
if(relationsList_now.size() == 0){
//表示不是更新的项目 需要插入当前项目本身的记录
dbSource.insertEddRelations(eddRelationTableName, relation_model);
}
}
}
public int changeNullToInt(Integer i){
if(i == null)
return 0;
else
return i;
}
public List<String> changeArrayToList(String[] strs){
List<String> result = new ArrayList<String>();
for(String str:strs){
str = RegexHandler.extractEngDecimalAndChinese(str);//对标签进行处理
result.add(str);
}
return result;
}
//匹配List中的数据和Map中的数据 返回匹配上得数量
public int matchListAndMap(List<String> tags, Map<String, Integer> description){
int count = 0;
for(String tag:tags){
if(description.containsKey(tag))
count++;
}
return count;
}
//找到当前项目同义词关联的项目 要求项目不相同 因为同一个项目可能包含多个同义词
public List<GatherProjectsModel> getRelatedGatherProjects(GatherProjectsModel model, List<String> synonymList){
List<GatherProjectsModel> result = new ArrayList<GatherProjectsModel>();
for(String name:synonymList){
Synonyms synonym = dbSource.getSynonymByName(synonymTableName, name);
if(synonym == null)
continue;//表示还不存在这样的标签
List<Synonymmings> synonymmingList = dbSource.selectSynonymmingListBySynonymId(synonymmingTableName, synonym.getId());
for(Synonymmings synonymming:synonymmingList){
GatherProjectsModel m = gatherDao.selectGPMById(gatherProjectsTableName, synonymming.getSynonymming_id());
if(model.getId() != m.getId()){
//判断m在result中是否存在
int i;
for(i = 0; i < result.size(); i++){
GatherProjectsModel tmp = result.get(i);
if(tmp.getId() == m.getId())
break;
}
if(i == result.size()){
result.add(m);
System.out.println("project:" + model.getId() + " match project:" + m.getId() + " by synonym:" + name);
}
}
}
}
return result;
}
//对url地址中的特殊字符进行转义处理
public String changeUrl(String url){
url = url.replace("/", "//");
url = url.replace("%", "/%");
url = url.replace("_", "/_");
url = url.replace("\\", "/\\");
return url;
}
//判断项目名的缩写是不是别名
public String getShortProjectName(String name, List<String> list){
String[] tmp = name.toLowerCase().split(" ");
String shortName = "";
for(String s:tmp){
String firstLetter = s.substring(0, 1);//取出第一个字符
shortName += firstLetter;
}
if(!"".equals(shortName)){
//如果该缩写在同义词结果中以单独的词存在 则说明是别名
for(String synonym:list){
//检查提取的别名中是否存在这个缩写形式
String[] words = synonym.split(" ");
for(String word:words){
if(shortName.equals(word)){
return shortName;
}
}
}
}
return "";//表示项目名的缩写不是项目的别名
}
//项目名是缩写 判断有没有相应的全称
public String getTotalProjectName(String name, List<String> list){
if(RegexHandler.othersExceptEng(name.toLowerCase())){
//表示项目名含有除小写英文字幕外的其他字符
return "";
}else{
//将项目名一个字符一个字符分隔开
String result = StringHandler.getFullName(name, list);
return result;//如果没有返回""
}
}
/**
* 对一个新软件的全部操作
* @param args
*/
@Transactional(propagation=Propagation.REQUIRED)
public void handleNewProject(GatherProjectsModel model, boolean updateOrNot){
//提取项目的homepage
String homepage = model.getHomepage();
//如果是null 不需要查找相同homepage的项目
List<GatherProjectsModel> sameHomepageList = new ArrayList<GatherProjectsModel>();
if(homepage != null && !"".equals(homepage)){
homepage = homepage.trim();
//查找所有相同homepage字段的项目
//判断homepage是否有http://或https://
int index_http = homepage.indexOf("http://");
int index_https = homepage.indexOf("https://");
if(index_http == 0){
homepage = homepage.substring(index_http + 7); //去除http://
}else if(index_https == 0){
homepage = homepage.substring(index_https + 8); //去除https://
}else{
//表示不是以http或https开头
}
if((homepage.lastIndexOf("/") == homepage.length()-1) && (homepage.length() != 0)){
//如果homepage的最后一个字符是/ 需要去除掉
homepage = homepage.substring(0, homepage.length() - 1);
}
if(homepage.length() > 0){
//为homepage添加http或https头
String homepage1 = "http://" + homepage;
String homepage2 = "https://" + homepage;
String homepage3 = "http://" + homepage + "/";
String homepage4 = "https://" + homepage + "/";
sameHomepageList = gatherDao.selectGPMBySameHomePage(gatherProjectsTableName, homepage, homepage1, homepage2, homepage3, homepage4, model.getId(), model.getSource());//认为一定是相同的项目
//查看sameHomepageList和当前的model存不存在来自同一社区的项目 如果存在则认为homepage匹配有问题 就将sameHomepageList清空
for(GatherProjectsModel m : sameHomepageList){
logger.info("project " + model.getId() + " and " + m.getId() + " match by homepage");
}
}
}
//如果项目名由多个单词组成,并且相同 则认为两个项目相同!cvs-fast-export 连字符特殊情况
List<GatherProjectsModel> sameNameList = new ArrayList<GatherProjectsModel>();
if(StringHandler_ProjectName.getWordNum(model.getName()) > 1){
//表示项目名由多个单词组成
sameNameList = gatherDao.selectGPMBySameName(gatherProjectsTableName, model.getName(), model.getId()); //找到表中相同名称的项目
for(GatherProjectsModel m : sameNameList){
logger.info("project " + model.getId() + " and " + m.getId() + " match by name");
}
}
//提取项目的同义词
List<String> synonymList = getSynonyms(model);//获取项目的同义词
List<GatherProjectsModel> matchedProjectList = getRelatedGatherProjects(model, synonymList);//在之前已经处理过的项目中找到有相同同义词的项目列表
for(GatherProjectsModel m : matchedProjectList){
logger.info("project " + model.getId() + " and " + m.getId() + " match by synonyms");
}
for(int i = 0; i < matchedProjectList.size(); i++){
GatherProjectsModel model2 = matchedProjectList.get(i);
if(!areTwoProjectsTheSame(model, model2)){
matchedProjectList.remove(i);//对于不是同一项目的在匹配列表中去除掉
i--;
}
}
for(GatherProjectsModel m : matchedProjectList){
logger.info("project " + model.getId() + " and " + m.getId() + " match by synonyms and verify");
}
//需要将两个相同项目的集合中的项目进行合并
matchedProjectList = mergeTwoList(sameHomepageList, matchedProjectList);
matchedProjectList = mergeTwoList(sameNameList, matchedProjectList);
/**
* 对项目同义词表进行合并,并添加项目之间的关联(匹配完之后的所有操作)
* 是不是相同的项目都做相同的操作 因为在edd_relations表中不论是删除还是更新都是先删除再插入
*/
handleAfterMatch(model,synonymList,matchedProjectList, updateOrNot);
}
/**
* 判断edd_relations中的记录合并到一起会不会导致项目中有相同的项目匹配到一起
* 如果存在返回null 如果不存在:返回匹配的结果
*/
//!!!!!!!!!同一社区直接删除
public String hasDiffProjFromSameCommunity(List<EddRelations> list){
String result = ",";
Map<Integer, Integer> map_project = new HashMap<Integer, Integer>();
Map<String, Integer> map_source = new HashMap<String, Integer>();
for(EddRelations relation:list){
//统计不同的项目id
String gather_projects_ids = relation.getGather_projects_ids();
gather_projects_ids = gather_projects_ids.substring(1, gather_projects_ids.length() - 1);
String[] idArray = gather_projects_ids.split(",");
for(String id:idArray)
map_project.put(Integer.parseInt(id), 1);
}
Set<Integer> idSet = map_project.keySet();
Iterator it = idSet.iterator();
while(it.hasNext()){
int id = (int)it.next();
GatherProjectsModel model = gatherDao.selectGPMById(gatherProjectsTableName, id);
String source = model.getSource();
if(map_source.containsKey(source)){
return null;//表示有重复社区的项目
}else{
map_source.put(source, 1);
result += id + ",";
}
}
return result;
}
/**
* 删除edd_relations表中对应id的记录 如果有osp_id则也要删除对应的open_source_projects表中的记录
*/
public void deleteExistEddRelations(EddRelations relation){
//删除之前对应的relation记录
int edd_relation_id = relation.getId();
dbSource.deleteEddRelationsItem(eddRelationTableName, edd_relation_id);
}
/**
* 将两个list<GatherProjectsModel>进行合并
*/
public List<GatherProjectsModel> mergeTwoList(List<GatherProjectsModel> list1, List<GatherProjectsModel> list2){
List<GatherProjectsModel> result = new ArrayList<GatherProjectsModel>();
Map<GatherProjectsModel, Integer> map = new HashMap<GatherProjectsModel, Integer>();
for(GatherProjectsModel model:list1){
if(!map.containsKey(model))
map.put(model, 1);
}
for(GatherProjectsModel model:list2){
if(!map.containsKey(model))
map.put(model, 1);
}
Set<GatherProjectsModel> keySet = map.keySet();
Iterator it = keySet.iterator();
while(it.hasNext()){
result.add((GatherProjectsModel) it.next());
}
return result;
}
/**
* 比较两个list中相同个数
*/
public List<String> getSameStringsInList(List<String> list1, List<String> list2){
List<String> result = new ArrayList<String>();
for(int i = 0; i < list1.size(); i++){
String str = list1.get(i);
String sameString = theMostSimilarString(str, list2);
if(sameString != null)
result.add(sameString);
}
return result;
}
/**
* 判断是不是有来自同一社区的项目
*/
}