Browse Source

完成推荐资产或设备接口

Jxing 6 years ago
parent
commit
00f3749c6b

+ 45 - 0
src/main/java/com/sagacloud/pojos/RecommendObject.java

@@ -0,0 +1,45 @@
+package com.sagacloud.pojos;
+/*
+ * Author: Jxing
+ * Create Time: 2018/11/13
+ */
+
+import com.alibaba.fastjson.JSONObject;
+
+public class RecommendObject implements Comparable {
+    private double similarity ;
+    private JSONObject obj;
+
+    public RecommendObject(double similarity, JSONObject obj){
+        this.similarity = similarity;
+        this.obj = obj;
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        RecommendObject current = (RecommendObject)o;
+        if(current.similarity > this.similarity){
+            return 1;
+        }else if(current.similarity == this.similarity){
+            return 0;
+        }
+        return -1;
+    }
+
+
+    public double getSimilarity() {
+        return similarity;
+    }
+
+    public void setSimilarity(double similarity) {
+        this.similarity = similarity;
+    }
+
+    public JSONObject getObj() {
+        return obj;
+    }
+
+    public void setObj(JSONObject obj) {
+        this.obj = obj;
+    }
+}

+ 5 - 2
src/main/java/com/sagacloud/route/Route.java

@@ -278,7 +278,10 @@ public class Route extends ExceptionHandlerBaseRoute {
                 .process(ContractMethods :: preQueryEq)
                 .to(InitEnvRoute.dataPlatform + "/object/subset_query?bridgeEndpoint=true")
                 .process(ContractMethods :: extractSupplierContractIds);
-    }
-
 
+        rest("/recommend").post()
+                .produces(MediaType.APPLICATION_JSON)
+                .route()
+                .process(RecommendProcessor::recommend);
+    }
 }

+ 159 - 0
src/main/java/com/sagacloud/route/processors/RecommendProcessor.java

@@ -0,0 +1,159 @@
+package com.sagacloud.route.processors;
+/*
+ * Author: Jxing
+ * Create Time: 2018/11/13
+ */
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.sagacloud.Exceptions.InvalidPostException;
+import com.sagacloud.pojos.RecommendObject;
+import com.sagacloud.utils.ExternalUrlUtil;
+import com.sagacloud.utils.HttpRequests;
+import com.sagacloud.utils.VendersUtil;
+import org.apache.camel.Exchange;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+public class RecommendProcessor {
+    static Map<String, String> dpVenderNameInfoCodeMap = new HashMap<>();
+    static double threshold = 0.25d;
+    static ArrayList<String> uselessWords = VendersUtil.createArrayList("集团", "有限", "公司", "科技", "技术", "信息");
+    static {
+        dpVenderNameInfoCodeMap.put("supplier", "Supplier");
+        dpVenderNameInfoCodeMap.put("insurer", "Insurer");
+        dpVenderNameInfoCodeMap.put("maintainer", "Maintainer");
+    }
+    public static void recommend(Exchange exchange) throws Exception {
+        String jsonStr = exchange.getIn().getBody(String.class);
+        JSONObject limit = null;
+        String venderType = null;
+        String venderName = null;
+        String pjId = null;
+        try {
+            JSONObject json = JSONObject.parseObject(jsonStr);
+            limit = json.getJSONObject("limit");
+            JSONObject criteria = json.getJSONObject("criteria");
+            venderType = criteria.getString("venderType");
+            venderName = criteria.getString("venderName");
+            pjId = criteria.getString("projectId");
+            if(venderType == null || !(venderType.equals("supplier") || venderType.equals("insurer") || venderType.equals("maintainer")))
+                throw new Exception();
+            if(venderName == null || venderName.length() == 0)
+                throw new Exception();
+            if(pjId == null || !pjId.startsWith("Pj"))
+                throw new Exception();
+        }catch (Exception ex){
+            throw new InvalidPostException("输入错误");
+        }
+        // map<厂商名, 对象JSONObject>
+        // 获取有厂商名, 并且没有绑定厂商id的对象
+        Map<String, JSONObject> map = getAllObjectMap(pjId, venderType);
+        if(map.size() == 0){
+            exchange.getOut().setBody(VendersUtil.successJsonMsg(""));
+            return;
+        }
+        ArrayList<JSONObject> arr = recommendObject(map, venderName);
+        if(arr.size() == 0){
+            exchange.getOut().setBody(VendersUtil.successJsonMsg(""));
+            return;
+        }
+        List<Object> finalArr = paging(arr, limit);
+        exchange.getOut().setBody(VendersUtil.returnJSONArray(new JSONArray(finalArr), (long)arr.size()));
+    }
+
+    private static List<Object> paging(ArrayList<JSONObject> arr, JSONObject limit) {
+        List<Object> retArr = new ArrayList<>();
+        Long from = 0L;
+        int count = arr.size();
+        Long limitSkip = limit == null ? null : limit.getLong("skip");
+        Integer limitCount = limit == null ? null : limit.getInteger("count");
+        if (limitSkip != null && limitCount != null) {
+            from = limitSkip;
+            count = limitCount;
+        }
+        for (long i = from; i < arr.size() && (i - from) < count; ++i) {
+            retArr.add(arr.get((int)i));
+        }
+        return retArr;
+    }
+
+    private static ArrayList<JSONObject> recommendObject(Map<String, JSONObject> map, String venderName) {
+        venderName = preprocessing(venderName);
+        PriorityQueue<RecommendObject> queue = new PriorityQueue<>();
+        for(String name : map.keySet()){
+            JSONObject single = map.get(name);
+            if(venderName.contains(name) || name.contains(venderName)){
+                RecommendObject obj = new RecommendObject(0.99d, single);
+                queue.add(obj);
+            }else {
+                double similarity = VendersUtil.levenshtein(venderName, name);
+                if(similarity > threshold){
+                    RecommendObject obj = new RecommendObject(similarity, single);
+                    queue.add(obj);
+                }
+            }
+        }
+        ArrayList<JSONObject> arrayList = new ArrayList<>();
+        while(!queue.isEmpty()){
+            arrayList.add(queue.poll().getObj());
+        }
+        return arrayList;
+    }
+
+    private static String preprocessing(String venderName) {
+        for(int i = 0; i < uselessWords.size(); ++i){
+            if(venderName.contains(uselessWords.get(i)))
+            {
+                venderName = venderName.replace(uselessWords.get(i), "");
+            }
+        }
+        return venderName;
+    }
+
+    private static Map<String, JSONObject> getAllObjectMap(String pjId, String venderType) throws Exception{
+        String type = venderType.equals("maintainer") ? "Eq" : "Pe";
+        String venderInfoCode = null;
+        if(venderType.equals("supplier"))
+            venderInfoCode = "DPSupplierID";
+        else if(venderType.equals("insurer"))
+            venderInfoCode = "DPInsurerID";
+        else
+            venderInfoCode = "DPMaintainerID";
+        JSONObject requestBody = new JSONObject();
+        JSONObject criteria = new JSONObject();
+        JSONArray typeArr = new JSONArray();
+        JSONArray valueArr = new JSONArray();
+        valueArr.add(null);
+        typeArr.add(type);
+        requestBody.put("criteria", criteria);
+        criteria.put("type", typeArr);
+        criteria.put(venderInfoCode, valueArr);
+        System.out.println(requestBody.toJSONString());
+        String result = HttpRequests.sendPost(ExternalUrlUtil.getInQueryUrl(pjId), requestBody.toString());
+        if(result.equals("")){
+            throw new Exception("数据平台访问异常");
+        }
+        JSONObject resultObj = JSONObject.parseObject(result);
+        if(!"success".equals(resultObj.getString("Result")))
+            throw new Exception("数据平台访问出错");
+        JSONArray content = resultObj.getJSONArray("Content");
+        Map<String, JSONObject> nameMap = new HashMap<>();
+        String infoCode = dpVenderNameInfoCodeMap.get(venderType);
+        for(int i = 0; i < content.size(); ++i){
+            JSONObject single = content.getJSONObject(i);
+            if(single == null)
+                continue;
+            JSONObject infos = single.getJSONObject("infos");
+            if(infos == null)
+                continue;
+            String nameValue = infos.getString(infoCode);
+            if(nameValue == null || nameValue.length() == 0)
+                continue;
+            if(!nameMap.containsKey(nameValue))
+                nameMap.put(nameValue, single);
+        }
+        return nameMap;
+    }
+}

+ 70 - 0
src/main/java/com/sagacloud/utils/VendersUtil.java

@@ -1,9 +1,12 @@
 package com.sagacloud.utils;
 
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
 
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -40,6 +43,15 @@ public class VendersUtil {
         jsonObj.put("resultMsg", msg);
         return jsonObj;
     }
+    public static String returnJSONArray(JSONArray arr, Long totalSize) {
+        JSONObject ret = JSONObject.parseObject("{\"Result\":\"success\",\"ResultMsg\":\"\", \"Content\":0}");
+        ret.put("ResultMsg", "");
+        ret.put("Count", (long) arr.size());
+        if(totalSize != null)
+            ret.put("TotalCount", totalSize);
+        ret.put("Content", arr);
+        return JSON.toJSONString(ret, SerializerFeature.WriteMapNullValue);
+    }
     public static JSONObject successJsonMsg(String msg, JSONArray arr){
         JSONObject jsonObj = new JSONObject();
         jsonObj.put("result", "success");
@@ -82,4 +94,62 @@ public class VendersUtil {
         }
         return set;
     }
+
+    /**
+     *   DNA分析   拼字检查   语音辨识   抄袭侦测
+     *
+     * @createTime 2012-1-12
+     */
+    public static double levenshtein(String str1,String str2) {
+        //计算两个字符串的长度。
+        int len1 = str1.length();
+        int len2 = str2.length();
+        //建立上面说的数组,比字符长度大一个空间
+        int[][] dif = new int[len1 + 1][len2 + 1];
+        //赋初值,步骤B。
+        for (int a = 0; a <= len1; a++) {
+            dif[a][0] = a;
+        }
+        for (int a = 0; a <= len2; a++) {
+            dif[0][a] = a;
+        }
+        //计算两个字符是否一样,计算左上的值
+        int temp;
+        for (int i = 1; i <= len1; i++) {
+            for (int j = 1; j <= len2; j++) {
+                if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
+                    temp = 0;
+                } else {
+                    temp = 1;
+                }
+                //取三个值中最小的
+                dif[i][j] = min(dif[i - 1][j - 1] + temp, dif[i][j - 1] + 1,
+                        dif[i - 1][j] + 1);
+            }
+        }
+        System.out.println("字符串\""+str1+"\"与\""+str2+"\"的比较");
+        //取数组右下角的值,同样不同位置代表不同字符串的比较
+        System.out.println("差异步骤:"+dif[len1][len2]);
+        //计算相似度
+        double similarity =1 - (double) dif[len1][len2] / Math.max(str1.length(), str2.length());
+        System.out.println("相似度:"+similarity);
+        return similarity;
+    }
+    private static int min(int... is) {
+        int min = Integer.MAX_VALUE;
+        for (int i : is) {
+            if (min > i) {
+                min = i;
+            }
+        }
+        return min;
+    }
+
+    public static ArrayList<String> createArrayList(String... elements) {
+        ArrayList<String> list = new ArrayList<String>();
+        for (String element : elements) {
+            list.add(element);
+        }
+        return list;
+    }
 }

+ 2 - 1
src/main/resources/documentation.md

@@ -337,7 +337,8 @@ post体:
             "count":50   // 查询跳过300条数据之后的50条 (按照关联性相似度排名)
         },
         "criteria":{
-            "venderType":"supplier|insurer|maintainer",     // 必填, 当前推荐的厂商类型
+            "projectId":"",                                 // 必填, 项目编号
+            "venderType":"supplier|insurer|maintainer",     // 必填, 当前推荐的厂商类型, 维修商结果是设备, 其他为资产
             "venderName":"***",                             // 必填, 当前推荐的厂商的名称
         }
     }