【需求】
某单位不动产登记系统,在对不动产数据(包括:使用权宗地、所有权宗地、自然幢)进行入库前,要进行属性检查,判断某些属性字段是否满足规则要求。主要规则可抽象为以下几类:
1.不允许为空值
2.必须来自某一特定字典,可为一个或多个值,多个值时以指定的分隔符隔开
3.位数固定,且全部为数字,或为数字与字母混合
4.为固定的某个值
5.一些位上的值会与其他位上的值有关系
【设计】
在进行该项功能设计时,为保证可扩展性,考虑制定规则配置的规范,将规则保存到配置文件中,代码部分只做对规则的解析和判定。接口传入参数采用GeoJSON的Feature格式,其属性为Dictionary<string,object>类型的集合。
配置文件规则如下:
文件内容为JSON集合类型。featureclass指定了要质检的图层(集合),fields为其待质检的属性。
一个配置项中,fields为各属性字段质检规则的集合。对一个属性质检规则而言:
- name为属性名,即该字段的名字(不区分大小写);
- nullable表示是否允许为空(如配置为false,表示不允许为空,若传入的要素该字段值为空,则不满足规则);
- collection表示该项值是否来源于集合,其中,seperator为取值的分隔符,list为取值集合(各值以英文半角逗号间隔。如取值集合为“01,011,012,013”,分隔符为“;”,则以下取值满足规则要求:“012;”、“01;011;”、“013”、“01;012”,而如下取值不满足:“01012”、“01011013”、“012,013”、“011,012;013;”);
- expression为正则表达式,即该字段取值需符合指定的正则表达式规则,如“^((G[BDEFSXY])|(J[ABCDEFSXY])|(ZW))$”(注意:部分特殊字符需进行转义,如“\”应写作 “\\”)。
如:
[
{
"featureclass": [
"ZD_SHYQ",
"ZD_SHYQ_WRK"
],
"fields": [
{
"name": "ZDTZM",
"nullable": false,
"expression": "^((G[BDEFSXY])|(J[ABCDEFSXY])|(ZW))$"
},
{
"name": "ZL",
"nullable": false
},
{
"name": "YT",
"nullable": false,
"collection": {
"seperator": ";",
"list": "01,011,012,013"
}
}
]
},
{
"featureclass": [
"ZRZ"
],
"fields": [
{
"name": "",
"nullable": false,
"collection": {
"seperator": "",
"list": ""
},
"expression": ""
}
]
}
]
【实现】
我们定义了一个类,来实现对单个要素的质检:
using GeoJSON.Net.Feature;
using GISWebService.HttpRequestContent;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
namespace GISWebService.Common
{
public class CheckFieldsHelper
{
private static string _ConfigFileName = "CheckFields.json";
private static List<FeatureClassRule> _FeatureClassRules = null;
public static List<FeatureClassRule> FeatureClassRules
{
get
{
if (null == _FeatureClassRules)
_FeatureClassRules = Load();
return _FeatureClassRules;
}
}
private static string GetConfigFile()
{
string s = System.IO.Path.Combine(AppSettings.PathByKey("tempdir"), _ConfigFileName);
return System.IO.File.Exists(s) ? s : "";
}
public static List<FeatureClassRule> Load()
{
string sPath = GetConfigFile();
List<FeatureClassRule> ls = new List<FeatureClassRule>();
if(!string.IsNullOrEmpty(sPath))
{
string sContent = System.IO.File.ReadAllText(sPath, System.Text.Encoding.Default);
ls = Newtonsoft.Json.JsonConvert.DeserializeObject<List<FeatureClassRule>>(sContent);
}
return ls;
}
public static CheckPropertyResult Check(string featureclass, Feature feature)
{
CheckPropertyResult result = new CheckPropertyResult() { ObjectID = -1, FieldInfo = new List<string>() };
Dictionary<string, object> dict = feature.Properties;
int nA = -1;
for (int n = 0; n < FeatureClassRules.Count; n++)
{
int m = FeatureClassRules[n].FeatureClassNames.FindIndex((e) => { return 0 == string.Compare(e, featureclass, true); });
if (m >= 0)
{
nA = n;
break;
}
}
if (nA < 0)
return new CheckPropertyResult();
List<FieldRule> lsRule = FeatureClassRules[nA].RuleOfFields;
foreach (var aPair in dict)
{
if (0 == string.Compare(aPair.Key, "objectid", true))
result.ObjectID = Convert.ToInt32(aPair.Value);
FieldRule fieldRule = null;
for (int k = 0; k < lsRule.Count; k++)
{
if (0 == string.Compare(lsRule[k].FieldName, aPair.Key, true))
{
fieldRule = lsRule[k];
break;
}
}
if (null == fieldRule)
continue;
string sValue = "";
if (null != aPair.Value)
sValue = aPair.Value.ToString().Replace(" ", "");
if (!fieldRule.Nullable)
{
if (string.IsNullOrEmpty(sValue))
{
result.FieldInfo.Add(string.Format("字段 {0} 取值不允许非空", aPair.Key));
continue;
}
}
if (!string.IsNullOrEmpty(sValue) && null != fieldRule.RuleOfCollection)
{
if (null != fieldRule.RuleOfCollection.Items && 0 < fieldRule.RuleOfCollection.Items.Count && !string.IsNullOrEmpty(fieldRule.RuleOfCollection.Seperator))
{
char[] cSeperator = fieldRule.RuleOfCollection.Seperator.ToCharArray();
string[] arrayValue = sValue.Split(cSeperator, StringSplitOptions.RemoveEmptyEntries);
foreach(var item in arrayValue)
{
if (0 > fieldRule.RuleOfCollection.Items.FindIndex(e => { return 0 == string.Compare(item, e, true); }))
{
result.FieldInfo.Add(string.Format("字段 {0} 取值不在指定的集合范围内", aPair.Key));
break;
}
}
}
}
if (!string.IsNullOrEmpty(sValue) && !string.IsNullOrEmpty(fieldRule.RegExp))
{
if(!(new Regex(fieldRule.RegExp).IsMatch(sValue)))
result.FieldInfo.Add(string.Format("字段 {0} 取值不符合规范", aPair.Key));
}
}
return (result.ObjectID < 0) ? new CheckPropertyResult() : result;
}
}
}
调用的地方比较简单,就不啰嗦了。
返回结果示例如下:
{
"status": 0,
"result": [
{
"layer": "ZRZ",
"info": [
{
"objectid": 1343,
"fields": [
"字段 ZDDM 长度不为 19 位",
"字段 BDCDYH 长度不为 28 位",
"字段 ZRZH 长度不为 24 位",
"字段 ZDZHTZM 不符合规范"
]
},
{
"objectid": 813,
"fields": []
}
]
},
{
"layer": "ZD_SHYQ",
"info": [
{
"objectid": 780,
"fields": [
"必填字段 QLR 为空",
"字段 YSDM 长度不为 10 位",
"字段 BDCDYH 长度不为 28 位",
"字段 ZDTZM 不符合规范",
"字段 DZWTZM 不符合规范"
]
}
]
}
]
}