一、根据中华人民共和国国家标准全国组织机构代码(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 {
//判断是否满足自定义区正则
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, code.charAt(i))*lastCodeW[i];
}
//求出来的和对11取模,然后 11-余数 得出下标
int index = 11 - num % 11;
//得出来的下标对应在(lastCodeMapNew)中的效验码
char lastCode = lastCodeMapNew[index];
//与原信用代码最后1位效验码作比对,看是否相同
return code.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;
for(int i = 0;i<17;i++){
num += (column.charAt(i)=='0'? 0 : getIndex(lastCodeMap,column.charAt(i)))*lastCodeW[i];
}
int index = 31 - num % 31;
char lastCode = lastCodeMap[index];
return column.charAt(17) == lastCode;
}
public boolean checkNineOrganizationCode(String code){
if(code==null){
return false;
}else {
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, code.charAt(i))*lastCodeW[i];
}
int index = 11 - num % 11;
char lastCode = lastCodeMapNew[index];
return code.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()) && checkNineOrganizationCode(arguments[0].get().toString().substring(8, 17));
}
}
}
@Override
public String getDisplayString(String[] children) {
return "check code";
}
}