hive自定义函数实现组织机构代码统一社会信用代码校验

Posted 玛哩嘛li哄

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hive自定义函数实现组织机构代码统一社会信用代码校验相关的知识,希望对你有一定的参考价值。

一、根据中华人民共和国国家标准全国组织机构代码(9位)编制规则实现规则校验

1、组织机构代码编码规则

1.1组织机构代码的组成

全国组织机构代码由八位数字(或大写拉丁字母)本体代码和一位数字(或大写拉丁字母)校验码组成。

1.2效验码生成规则

本体代码采用系列(即分区段)顺序编码方法

校验码按照以下公式计算:

C9=11-MOD(∑Ci(i=1→8)×Wi,11)

式中: MOD——代表求余函数;

i——代表代码字符从左至右位置序号;

Ci——代表第i位上的代码字符的值(具体代码字符见附表);

C9——代表校验码;

Wi——代表第i位上的加权因子,其数值见下表:

i

1

2

3

4

5

6

7

8

Wi

3

7

9

10

5

8

4

2

C9的值为1-9时,效验码为1-9;当C9的值为10时,校验码应用大写的拉丁字母X表示;当C9的值为11时校验码用0表示。

1.3代码的表示形式

为便于人工识别,应使用一个连字符“—”分隔本体代码与校验码。机读时,连字符省略。表示形式为:

xxxxxxxx—X

1.4自定义区

为满足各系统管理上的特殊需要,规定本体代码PDY00001至PDY99999为自定义区,供各系统编制内部组织机构代码使用。自定义区内编制的组织机构代码不作为个系统之间信息交换的依据。

1.5代码字符集

代码字符与机器处理字符数值对照表:

字符

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

G

H

数值

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

字符

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

数值

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

2、UDF代码实现

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

public class CheckNineOrganizationCode extends GenericUDF 

    //自定义区:为满足各系统管理上的特殊需要,本标准规定本体代码PDY00001至PDY99999为自定义区,供各系统编制内部组织机构代码使用。自定义区内编制的组织机构代码不作为各系统之间信息交换的依据
    private static final String patrnSpecial = "^PDY[0-9]5[0-9A-Z]1$";
    //(组织机构代码)9位正则表达式
    private static final String patrnOld = "^[0-9A-Z]9$";

    @Override
    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException 
        if (arguments.length!=1)
            throw new UDFArgumentLengthException("input arguments length less then one");
        
        if(!arguments[0].getCategory().equals(ObjectInspector.Category.PRIMITIVE))
        
            throw  new UDFArgumentTypeException(0,"input arguments type error");
        
        return PrimitiveObjectInspectorFactory.javaStringObjectInspector;
    

    //获取传进来的信用代码在代码字符集(lastCodeMap)中的位置,即机器处理用代码字符数值
    //例如传进来M,则对应的机器处理用代码字符数值为 22
    public int getIndex(char[] arr,char item)
        int index = 0;
        for(int i = 0;i<arr.length;i++)
            if(arr[i]== item )
                index = i;
            
        
        return index;
    
    
    public boolean checkNineOrganizationCode(String code)

        if(code==null || code.equals("PDY000000"))
            return false;
        else 
            StringBuilder codes = new StringBuilder(code);
            //判断是否满足自定义区正则
            if(code.matches(patrnSpecial))
                return true;
            else 
                if(!code.matches(patrnOld))
                    return false;
                else 
                    //代码字符集
                    char[] lastCodeMap = '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z';
                    //对应位置的加权因子,如位置0上的加权因子为3
                    int[] lastCodeW = 3, 7, 9, 10, 5, 8, 4, 2;
                    //对应位置的效验码
                    char[] lastCodeMapNew = '0','1','2','3','4','5','6','7','8','9','X','0';
                    int num = 0;
                    for(int i = 0; i < 8 ; i++)
                        //本体代码与加权因子对应各位相乘求和
                        num += getIndex(lastCodeMap, codes.charAt(i))*lastCodeW[i];
                    
                    //求出来的和对11取模,然后  11-余数 得出下标
                    int index = 11 - num % 11;
                    //得出来的下标对应在(lastCodeMapNew)中的效验码
                    char lastCode = lastCodeMapNew[index];
                    //与原信用代码最后1位效验码作比对,看是否相同
                    return codes.charAt(8) == lastCode;
                
            
        
    
    
    @Override
    public Object evaluate(DeferredObject[] arguments) throws HiveException 

        if (arguments[0].get()==null)
            return false;
        
        return checkNineOrganizationCode(arguments[0].get().toString());
    

    @Override
    public String getDisplayString(String[] children) 
        return "check code";
    

二、根据十八位统一社会信用代码编制规则实现规则校验

1、统一社会信用代码编码规则:

1.1统一社会信用代码的组成

统一社会信用代码由18位数字或者大写字母组成,但是字母不包括 I、O、Z、S、V

一共由五部分组成

第一部分:登记管理部门代码1位 (数字或大写英文字母)

第二部分:机构类别代码1位 (数字或大写英文字母)

第三部分:登记管理机关行政区划码6位 (数字)

第四部分:主体标识码(组织机构代码)9位 (数字或大写英文字母)

第五部分:校验码1位 (数字或大写英文字母)

1.2效验码生成规则

第18位校验码按照以下公式计算:(遇0则Ci为0)

C18=31-MOD(∑Ci(i=1→17)×Wi,31)

C18的值为1-31,在代码字符集中有对应的字符表示,即为对应的校验码

加权因子表如下:

i

1

2

3

4

5

6

7

8

9

10

Wi

1

3

9

27

19

26

17

20

29

25

i

11

12

13

14

15

16

17

Wi

13

13

8

24

10

30

28

1.3代码字符集

代码字符与机器处理字符数值对照表:

字符

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

G

数值

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

字符

H

J

K

L

M

N

P

Q

R

T

U

W

X

Y

0

数值

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

2、UDF代码实现

udf编写流程和全国组织结构代码实现一样并且可一并验证组织结构代码,在原有的基础上加上18位校验规则

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

public class CheckUnifiedSocialCreditCode extends GenericUDF 
    //整体18位正则表达式
    private static final String patrn = "^(([15N]1[1239]1)|([248A]1[19]1)|([3]1[123459]1)|([67]1[129]1)|([Y]1[1]1)|([9]1[123]1))(([1]1[012345]1)|([2]1[123])|([3]1[1234567]1)|([4]1[123456]1)|([5]1[01234]1)|([6]1[12345]1)|([7]1[1]1)|([8]1[12]1))[A-Y\\\\d]14$";
    //自定义区正则表达式
    private static final String patrnSpecial = "^PDY[0-9]5[0-9A-Z]1$";
    //组织机构代码9位正则表达式
    private static final String patrnOld = "^[0-9A-Z]9$";

    @Override
    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException 
        if (arguments.length!=1)
            throw new UDFArgumentLengthException("input arguments length less then one");
        
        if(!arguments[0].getCategory().equals(ObjectInspector.Category.PRIMITIVE))
        
            throw  new UDFArgumentTypeException(0,"input arguments type error");
        
        return PrimitiveObjectInspectorFactory.javaStringObjectInspector;
    

    public int getIndex(char[] arr,char item)
        int index = 0;
        for(int i = 0;i<arr.length;i++)
            if(arr[i]==(item))
                index = i;
            
        
        return index;
    

    public boolean checkEighteenOrganizationCode(String column)
        if (column.substring(8,17).matches(patrnSpecial)) 
            return true;
        
        //代码字符集,不包括I,O,Z,S,V,也用于判断最后一位是否与其计算出对应的效验码值相同
        char[] lastCodeMap = '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','T','U','W','X','Y','0';
        //加权因子值列表
        int[] lastCodeW = 1,3,9,27,19,26,16,17,20,29,25,13,8,24,10,30,28;
        int num = 0;
        StringBuilder columns = new StringBuilder(column);
        for(int i = 0;i<17;i++)
            num += (columns.charAt(i)=='0'? 0 : getIndex(lastCodeMap,columns.charAt(i)))*lastCodeW[i];
        
        int index = 31 - num % 31;
        char lastCode = lastCodeMap[index];
        return columns.charAt(17) == lastCode;
    

    public boolean checkNineOrganizationCode(String code)
        if(code==null)
            return false;
        else 
            StringBuilder codes = new StringBuilder(code);
            if(code.matches(patrnSpecial))
                return true;
            else 
                if(!code.matches(patrnOld))
                    return false;
                else 
                    char[] lastCodeMap = '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z';
                    int[] lastCodeW = 3, 7, 9, 10, 5, 8, 4, 2;
                    char[] lastCodeMapNew = '0','1','2','3','4','5','6','7','8','9','X','0';
                    int num = 0;
                    for(int i = 0; i < 8 ; i++)
                        num += getIndex(lastCodeMap, codes.charAt(i))*lastCodeW[i];
                    
                    int index = 11 - num % 11;
                    char lastCode = lastCodeMapNew[index];
                    return codes.charAt(8) == lastCode;
                
            
        
    

    @Override
    public Object evaluate(DeferredObject[] arguments) throws HiveException 

        if (arguments[0].get()==null)
            return false;
        else 
            if(!arguments[0].get().toString().trim().matches(patrn))
                return false;
            else 
                return checkEighteenOrganizationCode(arguments[0].get().toString().trim()) || checkNineOrganizationCode(arguments[0].get().toString().substring(8, 17));
            
        
    

    @Override
    public String getDisplayString(String[] children) 
        return "check code";
    

以上是关于hive自定义函数实现组织机构代码统一社会信用代码校验的主要内容,如果未能解决你的问题,请参考以下文章

社会信用代码是啥

如何查询统一社会信用代码

18位的统一社会信用代码是啥?

组织机构代码统一社会信用代码等命名规则

统一信用代码是啥

精准准确的统一社会信用代码正则(js)