lua基于oopclass的属性节点类 和 集合类
--[[----------------------------------------------------------------------------
--@ Descrption: 属性节点类库
--@ Changes:
-------------------------------------------------------------------------------]] -- 引入面向对象的类机制
local oopclass = require("misc.oopclass")
local class = oopclass.class -- 引入断言库
local assertlib = require("misc.assertlib")
local typeAssert = assertlib.typeAssert -- 属性节点
local AttrNode = class()
AttrNode.__abstract = true --[[
Function: AttrNode.__attrInitialize
Description: 初始化节点属性
Parm: self(object):对象本身
source(table): 外部设置属性节点表
attrs(table): 属性名称表
return: NA
]]
AttrNode.__attrInitialize = function ( self, source, attrs )
typeAssert(source, "table")
typeAssert(attrs, "table") -- 记录合法的属性名称,用于修改属性
self.__legal_attrs = attrs -- 将参数值记录到对象
for _,para in ipairs(attrs) do
if source[para] then
self[para] = source[para]
end
end -- 只读属性表
self.__readonly_attrs = {}
end --[[
Function: AttrNode.__checkAttrLegal
Description: 校验属性名合法性
Parm: self(object):对象本身
name(string): 属性名
return: bool: 是否校验通过
]]
AttrNode.__checkAttrLegal = function ( self, name )
typeAssert(name, "string") local legalAttrs = self.__legal_attrs -- 只有在合法列表中的属性才校验通过
for _,attr in ipairs(legalAttrs) do
if name == attr then
return
end
end assert(false, "attr name is illegal!")
end --[[
Function: AttrNode.setAttribute
Description:设置节点属性
Parm: self(object):对象本身
name(string): 属性名
value(string): 属性值
return: 菜单节点对象
]]
AttrNode.setAttribute = function (self, name, value)
typeAssert(name, "string") -- 属性类型支持三种类型:
-- string, 例如 菜单id
-- number, 例如 权限
-- table, 例如 backendFile
-- function, 例如 过滤函数
-- nil, 保证可选的参数可以被设置为nil
typeAssert(value, "string", "number", "table", "function", "nil") self:__checkAttrLegal(name) -- 只读属性,不允许修改
for _,readOnlyAttr in ipairs(self.__readonly_attrs) do
if readOnlyAttr == name then
-- 直接返回
return self
end
end self[name] = value -- 链式写法需要
return self
end --[[
Function: AttrNode.getAttribute
Description:设置节点属性
Parm: self(object):对象本身
name(string): 属性名
return: 属性值
]]
AttrNode.getAttribute = function (self, name)
typeAssert(name, "string") self:__checkAttrLegal(name) return self[name]
end --[[
Function: AttrNode.defineAttrReadOnly
Description:设置指定属性为只读
Parm: self(object):对象本身
name(string): 属性名
return: 属性值
]]
AttrNode.defineAttrReadOnly = function (self, name)
typeAssert(name, "string") self:__checkAttrLegal(name) -- 记录属性到只读属性表
table.insert(self.__readonly_attrs, name) -- 链式写法需要
return self
end --[[
Function: AttrNode.searchCollection
Description:搜索节点的附属集合(collection), 例如 子菜单 和 功能区
Parm: self(object):对象本身
collection(table): 待搜索的集合
func(function): 对于集合中的元素执行的操作
return: NA
]]
AttrNode.searchCollection = function (self, collection, func)
typeAssert(collection, "table")
typeAssert(func, "function") local isloop = nil for index,item in ipairs(collection) do
isloop = func(item, index) -- 后面不需要循环了
if isloop == false then
break
end
end
end --[[
Function: AttrNode.__attrToNVPair
Description: 将属性转换为 名值对 NVPair(name value pair): "name:value"
Parm: self(object):对象本身
name(string): 属性名
splitter(string): name 和 value之间的分隔符
return: NVPair(string)
]]
AttrNode.__attrToNVPair = function (self, name, splitter)
typeAssert(name, "string")
typeAssert(splitter, "string") self:__checkAttrLegal(name) local quotedName = string.format("%q", name) local ret = quotedName ..splitter local val = self[name]
local typeOfVal = type(val) local valstr = "null" if typeOfVal == "nil" then
valstr = "null"
elseif typeOfVal == "string" then
valstr = string.format("%q", val)
elseif typeOfVal == "number" then
valstr = tostring(val)
-- 支持backendFile = {"xx", "yy"}的情况
elseif typeOfVal == "table" then
local cache = {}
for _,v in ipairs(val) do
if type(v) == "string" then
local quotedStr = string.format("%q", v)
table.insert(cache, quotedStr)
end
end
local contentStr = table.concat(cache, ",")
valstr = string.format("[%s]", contentStr)
else
end ret = ret .. valstr return ret
end --[[
Function: AttrNode.__getNVPairsofAttrs
Description: 将节点属性转换为字符串NVPair,缓存在表中
Parm: self(object):对象本身
splitter(string): name 和 value之间的分隔符
attrs(table): 指定属性名集合,可选
return: cache(table)
]]
AttrNode.__getNVPairsofAttrs = function (self, splitter, attrs)
typeAssert(splitter, "string")
typeAssert(attrs, "table", "nil") -- 如果未指定属性集合,确定为所有合法属性
if not attrs then
attrs = self.__legal_attrs
end local cache = {} self:searchCollection(attrs, function ( item, index )
-- every cache element is name:value
table.insert(cache, self:__attrToNVPair(item, splitter))
end) return cache
end --[[
Function: AttrNode.__nodeToJSON
Description: 将节点转换为JSON数据格式
Parm: self(object):对象本身
attrs(table): 指定属性名集合,可选
return: json(string)
]]
AttrNode.__nodeToJSON = function (self, attrs)
typeAssert(attrs, "table", "nil") local cache = self:__getNVPairsofAttrs(":", attrs) -- produce result: name1:value1, name2:value2
local contentStr = table.concat(cache, ",") -- wrap content with bracket, get JSON
local jsonStr = string.format("{%s}", contentStr) return jsonStr
end -- 将此类返回
return AttrNode
--[[----------------------------------------------------------------------------
--@ Descrption: 集合类库
--@ Changes:
-------------------------------------------------------------------------------]] -- 引入面向对象的类机制
local oopclass = require("misc.oopclass")
local class = oopclass.class
local instanceof = oopclass.instanceof -- 引入属性节点类
local AttrNode = require("misc.attrnodeclass") -- 引入断言库
local assertlib = require("misc.assertlib")
local typeAssert = assertlib.typeAssert -- 集合节点
local CollectionNode = class(AttrNode) --[[
Function: CollectionNode.__init__
Description:实例初始化
Parm: self(object):对象本身。
itemProtoDesc(table): 集合成员原型描述,包括
{
class -- 集合成员的类
keyName -- 集合成员的主键
}
return: 无
]]
CollectionNode.__init__ = function ( self, itemProtoDesc )
typeAssert(itemProtoDesc, "table")
-- 集合成员的类
typeAssert(itemProtoDesc.class, "table")
-- 集合成员主键,用户查找、添加、删除等
typeAssert(itemProtoDesc.keyName, "string") -- 集合成员的描述
self.__itemProtoDesc = itemProtoDesc -- 集合成员的存储表
self.__itemSet = {} -- 集合成员静态修改器表
self.__staticModFuncs = {} -- 集合成员动态修改器表
self.__dynamicModFuncs = {}
end --[[
Function: CollectionNode.findItem
Description:按照主键值查集合成员
Parm: self(object):对象本身。
keyValue(string): 主键值
return: targetObj, targetIndex : 目标对象, 目标对象下标
]]
CollectionNode.findItem = function ( self, keyValue )
typeAssert(keyValue, "string") -- 查找
local targetObj = nil
local targetIndex = nil
local keyName = self.__itemProtoDesc.keyName
self:searchCollection(self.__itemSet, function ( item, index )
if keyValue == item:getAttribute(keyName) then
targetObj = item
targetIndex = index
return false
end
end) return targetObj, targetIndex
end --[[
Function: CollectionNode.addItem
Description:添加集合成员
Parm: self(object):对象本身。
itemTable(table): 集合成员原始数据表
return: self
]]
CollectionNode.addItem = function ( self, itemTable )
typeAssert(itemTable, "table") -- 类型要与原型一致
local itemClass = self.__itemProtoDesc.class
local itemObj = itemClass(itemTable)
if not instanceof(itemObj, itemClass) then
return self
end -- key值异常保护
local keyName = self.__itemProtoDesc.keyName
local keyValue = itemObj:getAttribute(keyName)
if not keyValue then
return self
end -- 将key属性设置对只读
itemObj:defineAttrReadOnly(keyName) -- 新添加项的key值,不允许与现有表中项的key值重复!
-- 在表空间中, key表示的对象是唯一的, 在新添加表项时候, 需要检查冲突,
-- 只有在没有冲突的情况下, 才能添加成功。
-- 这种做法的考虑是,代码包化的背景下,addItem 分散在不同目录中,
-- 如果支持覆盖, 后添加者会将已有项覆盖掉,造成故障!!!
-- 对于正常的覆盖情况, 请先 调用 removeItem 然后 调用 addItem
local sameKeyObj, sameKeyIndex = self:findItem(keyValue)
-- 如果有重复,则报错
if sameKeyObj then
error("addItem keyName("..keyName..")'s keyValue("..keyValue..") conflict!")
end -- 将新类型添加进去
table.insert(self.__itemSet, itemObj) -- 返回集合对象本身,支持链式写法
return self
end --[[
Function: CollectionNode.removeItem
Description:删除指定集合成员
Parm: self(object):对象本身。
keyValue(string): 集合主键值
return: self
]]
CollectionNode.removeItem = function ( self, keyValue )
typeAssert(keyValue, "string") -- 按照主键,查找到集合成员,删除
local targetObj, targetIndex = self:findItem(keyValue)
if targetObj then
table.remove(self.__itemSet, targetIndex)
end -- 返回集合对象本身,支持链式写法
return self
end --[[
Function: CollectionNode.clearItem
Description:清空集合中所有成员
Parm: self(object):对象本身。
return: self
]]
CollectionNode.clearItem = function ( self, keyValue )
typeAssert(keyValue, "string") -- 重新设置为空表
self.__itemSet = {} -- 返回集合对象本身,支持链式写法
return self
end --[[
Function: CollectionNode.searchItem
Description: 遍历集合成员对象
Parm: self(object):对象本身
func(function): 对于集合成员执行的操作
return: self
]]
CollectionNode.searchItem = function (self, func)
typeAssert(func, "function") -- 遍历
self:searchCollection(self.__itemSet, func) -- 返回集合对象本身,支持链式写法
return self
end --[[
Function: CollectionNode.loadConfig
Description: 以配置表形式加载规则
Parm: self(object):对象本身
configTable(table):配置表
return: self
]]
CollectionNode.loadConfig = function (self, configTable)
typeAssert(configTable, "table") -- 遍历configTable,设置到管理表中
self:searchCollection(configTable, function ( item, index )
self:addItem(item)
end) -- 返回集合对象本身,支持链式写法
return self
end --[[
Function: CollectionNode.addModifier
Description: 添加加载器。
加载器就是一个匿名函数,函数体中定义规则的修改语句(CRUD)。
与loadConfig形成互补,支持分散注册规则(模块化要求),和修改已有规则(定制要求)。
同一表对象,所有addModifier语句所属文件,在编译阶段拼接为一个文件 xxx_modifier.lua。
Parm: self(object):对象本身
modFunc(function):修改规则函数,无入参,无返回值
return: self
]]
CollectionNode.addModifier = function (self, modFunc)
typeAssert(modFunc, "function") table.insert(self.__staticModFuncs, modFunc) -- 返回集合对象本身,支持链式写法
return self
end --[[
Function: CollectionNode.loadModifier
Description: 执行所有的加载器函数。
与addModifier接口逻辑配套,
在require("xxx_modifier.lua")之后,调用此函数,完成规则修改功能。
Parm: self(object):对象本身
return: self
]]
CollectionNode.loadModifier = function (self)
-- 执行所有加载器函数
for _,modFunc in ipairs(self.__staticModFuncs) do
modFunc()
end -- 返回集合对象本身,支持链式写法
return self
end --[[
Function: CollectionNode.runModifier
Description: 运行加载器,加载器定义与addModifier相同。
与addModifier不同的是,此函数会将加载器函数,立刻执行,完成动态修改规则。
说明:
1、loadConfig/addModifier&loadModifier 是为静态配置设计(第一次加载模块时),
2、runModifier为动态配置设计,在任意文件中插入此语句,在将来运行到此文件,才加载规则。
Parm: self(object):对象本身
modFunc(function):修改规则函数,无入参,无返回值
return: self
]]
CollectionNode.runModifier = function (self, modFunc)
typeAssert(modFunc, "function") -- 遍历 已经执行过的 动态配置的修改器函数
for _,modFuncCache in ipairs(self.__dynamicModFuncs) do
-- 如果已经执行过,则不再执行, 避免 addItem 执行多次的情况
if modFuncCache == modFunc then
return self
end
end modFunc() table.insert(self.__dynamicModFuncs, modFunc) -- 返回集合对象本身,支持链式写法
return self
end -- 将此类返回
return CollectionNode
lua基于oopclass的属性节点类 和 集合类的更多相关文章
- [原创]cocos2d-x研习录-第二阶 概念类之节点类(CCNode)
节点类CCNode在基本概念中并不存在,它是为了建立基本概念之间的关联关系而抽象出来的中间辅助类.这个类在Cocos2D-x中极为重要,它为概念类之间搭建了一座宏伟的桥梁.它的继承关系图如下: ...
- cocos2dx[3.2](6) 节点类Node
与2.x相比,节点类Node的属性和功能做了大幅度的修改与增加. Node类是绝大部分类的父类(并不是所有的类,例如Director类是直接继承Ref类的),如Scene.Layer.Sprite以及 ...
- 初探JavaScript(一)——也谈元素节点、属性节点、文本节点
Javascript大行其道的时候,怎么能少了我来凑凑热闹^_^ 基本上自己对于js的知识储备很少,先前有用过JQuery实现一些简单功能,要论起JS的前世今生,来龙去脉,我就一小白.抱起一本< ...
- Labview中的属性节点
获取(读取)和/或设置(写入)引用的属性.通过属性节点对本地或远程应用程序实例.VI或对象获取或设置属性和方法也可通过属性节点访问LabVIEW类的私有数据. 属性节点可自动调整为用户所引用的对象的类 ...
- C# 读取xml节点类容
这是一个测试节点类容的获取 这是控制台代码部分 注意的应用文件 :using.system.Xml using System; using System.Collections.Generic; us ...
- MyBatis之基于XML的属性与列名映射
上一博客主要是对单表的增删改查,比较简单,而且每个属性与table表的列都是一一对应名字也一样,今天主要学习属性与table表列名不一致的处理,主要有两种一是属性与列名不一致,二是枚举的情况,这里暂时 ...
- 【游戏开发】在Lua中实现面向对象特性——模拟类、继承、多态
一.简介 Lua是一门非常强大.非常灵活的脚本语言,自它从发明以来,无数的游戏使用了Lua作为开发语言.但是作为一款脚本语言,Lua也有着自己的不足,那就是它本身并没有提供面向对象的特性,而游戏开发是 ...
- Ignite集群管理——基于静态IP的节点发现
Ignite作为分布式内存,集群管理必不可少,Ignite支持基于组播,静态IP,Zookeeper,JDBC等方式发现节点,本文主要介绍基于静态IP的节点发现. 两个最重要的TCP通信设置类: 1. ...
- 并发编程概述 委托(delegate) 事件(event) .net core 2.0 event bus 一个简单的基于内存事件总线实现 .net core 基于NPOI 的excel导出类,支持自定义导出哪些字段 基于Ace Admin 的菜单栏实现 第五节:SignalR大杂烩(与MVC融合、全局的几个配置、跨域的应用、C/S程序充当Client和Server)
并发编程概述 前言 说实话,在我软件开发的头两年几乎不考虑并发编程,请求与响应把业务逻辑尽快完成一个星期的任务能两天完成绝不拖三天(剩下时间各种浪),根本不会考虑性能问题(能接受范围内).但随着工 ...
随机推荐
- C# 新语法收集
内联变量 使用int.tryparst时,先要申明变量,用于out参数 int d; int.tryparse(s,out d); 使用内联变量写法可以如下.功能一样简化了写化 int.trypars ...
- 使用template
1.放置html片段模板 <script id="tpl" type="text/html"> <p>$title</p>& ...
- poj 3080 Blue Jeans (暴力枚举子串+kmp)
Description The Genographic Project is a research partnership between IBM and The National Geographi ...
- Ubuntu常用软件安装(小集合)
跨平台系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#linux Linux包系列的知识:https://www.cnblogs.com/dun ...
- webpack入门(六) API in modules
A quick summary of all methods and variables available in code compiled with webpack. 用webpack编译的一些变 ...
- 闲聊javascript继承和原型
javascript继承已经是被说烂的话题了,我就随便聊一点~ 一.javascript的复制继承 javascript的继承有复制继承和原型继承,基于复制继承用的不太多,而且无法通过instance ...
- BZOJ 1143: [CTSC2008]祭祀river(最大独立集)
题面: https://www.lydsy.com/JudgeOnline/problem.php?id=1143 一句话题意:给一个DAG(有向无环图),求选出尽量多的点使这些点两两不可达,输出点个 ...
- String:字符串常量池
String:字符串常量池 作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串常量池: 字 ...
- JavaScript(JS)基本语法(一)
https://www.cnblogs.com/haiyan123/p/7577598.html 一.JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入 ...
- 第三十七篇-BottomNavigationVIew底部导航的使用
效果图: 添加底部导航和viewpaper 设置底部导航在底部 app:layout_constraintBottom_toBottomOf="parent" 新建四个fragme ...